프롬프트에서 현재 디렉터리를 참조하고 싶습니다.
예를 들어, 이렇게 하면:
mkdir $'new\nline'; cd $'new\nline'
$'new\nline'
프롬프트 를 인쇄하는 대신 리터럴 개행 문자를 표시하고 싶습니다 .
\
다음에서 백슬래시()를 인쇄하려고 하면 흥미로운 동작이 나타납니다 bash 5.0.9
.
p='\\n' && echo -E "${p@P}" # 2 slashes; output = '\n'
p='\\\\n' && echo -E "${p@P}" # 4 slashes; output = '\n'
p='\\\\\\n' && echo -E "${p@P}" # 6 slashes; output = '\\n'
p='\\\\\\\\n' && echo -E "${p@P}" # 8 slashes; output = '\\n'
노트:${parameter@P}
parameter
힌트인 것처럼 값을 확장한 결과인 문자열입니다.
출력이 (2와 4) 및 (6과 8) 슬래시와 동일한 이유는 무엇입니까?
이러한 혼란을 고려하면 다음과 같습니다.
mkdir '\\n' && cd '\\n'
\\n
프롬프트에 : \\\\n
또는 로 표시되도록 프로그래밍 방식으로 문자열로 변환하는 방법 $'\\\\n'
과 리터럴 개행 상황을 처리하는 방법을 알 수 없습니다 .
프롬프트에서 참조되는 디렉터리 이름을 얻으려면 어떻게 해야 합니까? 예:
~
하위 디렉터리를 표시하고 그$HOME
앞에 표시~/
- 필요한 경우에만 다른 경로를 탈출하세요
- 표시 문자열의 복사-붙여넣기는 현재 디렉토리를 참조하는 유효한 쉘 토큰입니다.
예를 들어 "$HOME/dir with spaces"
다음과 같아야 합니다.
~/dir\ with\ spaces
~/$'dir with spaces'
~/'dir with spaces'
답변1
Bash는 프롬프트에 및를 포함하는 경우 에만 \w
프롬프트에 cd $'/tmp/new\nline'
표시됩니다 . /tmp/newline
리터럴 줄 바꿈을 인쇄하지 않는 것 같지만 명시적인 출력 형식도 아닙니다.
${var@P}
\u
사용자 이름, \h
호스트 이름, \w
작업 디렉터리 와 같은 항목에 대해 프롬프트 이스케이프를 확장하도록 설계되었습니다 . 반대로 ${var@Q}
어떤 인용 결과가 더 유용할까요?
settings PS1='${PWD@Q}\$ '
, 프롬프트가 표시됩니다: $'/tmp/new\nline'$
또는 '/tmp'$
경로가 더 나은 경우. 또 다른 옵션은 PS1='$(printf "%q" "$PWD")\$ '
경우에 따라 다른 따옴표를 제공하는 것입니다. 예를 들어 "좋은" 경로의 경우 따옴표를 생략합니다 /tmp$
.
홈 디렉터리를 물결표로 표시하려면 한 가지 옵션은 수동으로 바꾸는 것입니다.
set_ppath() {
printf -v ppath "%q" "$PWD"
ppath="${ppath/$HOME/"~"}";
}
PROMPT_COMMAND=set_ppath
PS1='$ppath\$ '
아직도 언급하고 있어모두그러나 그 일부를 참조해야 하는 경우에는 경로입니다. 이 문제를 해결하려면 조금씩 이 길을 따라가야 한다고 생각합니다.
그런데 백슬래시가 왜 이렇게 접혀 있는지 모르겠습니다 ${var@P}
.
답변2
ilkkachu의 답변을 바탕으로 다음을 생각해 냈습니다.
PROMPT_COMMAND=_prompt_bash_set
_prompt_bash_set() {
# Working directory
local prefix='' # Used to contain '~' if $PWD directory is under $HOME
local dir=$PWD
# Replace leading $HOME with ~ if at beginning of string
case "$PWD"/ in # Extra slash at end prevents substring match
"$HOME"/) # $PWD == $HOME itself
prefix=\~ # no trailing /
dir='' ;;
"$HOME"/?*) # $PWD is a subdir of $HOME
prefix=\~/ # Add trailing / so that possibly quoted string goes after ~/ for path validity
dir=${PWD#$HOME/} ;; # Remove $HOME and / as this is now in $prefix
esac
if [[ $PWD != $HOME ]]; then # $PWD != $HOME
# Avoid ${PWD@Q} as it produced a literal \n inside $''
printf -v dir '%q' "$dir" # Quote directory minus $HOME
# Replace a single slash with 4!?! slashes
# https://unix.stackexchange.com/q/543473/143394
dir=${dir//\\/\\\\\\\\}
# Prevent command and variable substitution:
dir=${dir//\`/\\\`} # escape ` as \`
dir=${dir//\$/\\\$} # escape $ as \$
fi
PS1='\u@\h:'$dir'\$ '
}
$PS1
여기에는 변수를 통하지 않고 리터럴 텍스트로 참조된 디렉터리가 포함됩니다 .
계속할 수 있다는 장점이 있어요디렉토리의 컬러 슬래시내 눈은 분석하기가 더 쉽다고 생각합니다.