귀하의 질문에 언급 한 것과 동일한 결과를 얻으려면 필요한 것은 다음과 같습니다.
PS1='${PS2c##*[$((PS2c=0))-9]}- > '
PS2='$((PS2c=PS2c+1)) > '
뒤 틀릴 필요는 없습니다. 이 두 줄은 POSIX 호환성에 가까운 것으로 가장하는 모든 쉘에서 모든 작업을 수행합니다.
- > cat <<HD
1 > line 1
2 > line $((PS2c-1))
3 > HD
line 1
line 2
- > echo $PS2c
0
그러나 나는 이것을 좋아했다. 그리고 나는 이것이 더 잘 작동하는 것의 기본을 보여주고 싶었습니다. 그래서 이것을 조금 편집했습니다. 나는 /tmp
지금 그것을 붙였다. 그러나 나는 나 자신을 위해 그것을 유지할 것이라고 생각한다. 여기 있습니다 :
cat /tmp/prompt
프롬프트 스크립트 :
ps1() { IFS=/
set -- ${PWD%"${last=${PWD##/*/}}"}
printf "${1+%c/}" "$@"
printf "$last > "
}
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
PS2='$((PS2c=PS2c+1)) > '
참고 : 최근에 yash를 배웠 으므로 어제 만들었습니다. 어떤 이유로 든 %c
문자열을 사용하여 모든 인수의 첫 번째 바이트를 인쇄하지는 않습니다 . 문서는 해당 형식의 와이드 문자 확장과 관련이 있으므로 관련이있을 수 있습니다.%.1s
그게 다야. 두 가지 주요 사항이 있습니다. 그리고 이것은 다음과 같습니다 :
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 >
파싱 $PWD
$PS1
평가 될 때마다 구문 분석 및 인쇄 $PWD
되어 프롬프트에 추가됩니다. 그러나 나는 전체 $PWD
화면이 붐비 는 것을 좋아하지 않기 때문에 현재 경로에있는 모든 이동 경로의 첫 글자 만 현재 디렉토리로 내려 가기를 원합니다. 이처럼 :
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cd /
/ > cd ~
/h/mikeserv >
여기 몇 가지 단계가 있습니다.
IFS=/
우리는 전류를 분리해야 $PWD
하고 가장 신뢰할 수있는 방법은 $IFS
split on /
입니다. 이후에는 전혀 신경 쓰지 않아도됩니다. 여기에서 모든 분할 $@
은 다음과 같은 다음 명령에서 쉘의 위치 매개 변수 배열에 의해 정의됩니다 .
set -- ${PWD%"${last=${PWD##/*/}}"}
그래서 이것 좀 까다로운하지만 중요한 것은 그 우린 분할이다 $PWD
에 /
상징. 또한 매개 변수 확장을 사용 $last
하여 가장 왼쪽 /
슬래시 와 가장 오른쪽 슬래시 사이에 값이 발생한 후 모든 것에 할당합니다 . 이런 식으로 난 그냥에있어 경우에 알고 /
및이 하나가 /
후 $last
여전히 전체를 동일합니다 $PWD
및 $1
비어 있습니다. 이것은 중요하다. 또한에 할당하기 전에 $last
꼬리 끝에서 벗겨 냅니다.$PWD
$@
printf "${1+%c/}" "$@"
그래서 여기 -만큼 ${1+is set}
우리 printf
처음 %c
각 우리의 쉘의 인수 haracter - 우리가 우리의 현재의 각 디렉토리로 설정 한 $PWD
- 덜 최상위 디렉토리 -에 분할 /
. 따라서 기본적으로 모든 디렉토리의 첫 번째 문자를 $PWD
제외하고 맨 위의 문자 만 인쇄합니다 . 이 $1
설정은 전혀 설정되지 않은 경우에만 발생하지만 루트 /
또는에서 /
와 같이 제거 되지 않은 경우에만 발생합니다 /etc
.
printf "$last > "
$last
방금 최상위 디렉토리에 할당 한 변수입니다. 이제 이것이 최상위 디렉토리입니다. 마지막 문장의 인쇄 여부를 인쇄합니다. 그리고 >
좋은 측정을 위해서는 깔끔한 약간의 시간이 걸립니다 .
그러나 증가에 대해 무엇입니까?
그리고 $PS2
조건부 문제가 있습니다. 아래에서 여전히 찾을 수있는 방법을 이전에 보여주었습니다. 이것은 근본적으로 범위 문제입니다. 그러나 당신이 많은 printf \b
ackspaces 를 시작하고 그들의 캐릭터 수의 균형을 맞추고 싶지 않다면 조금 더 있습니다. 그래서 나는 이것을한다 :
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
다시, ${parameter##expansion}
하루를 저장합니다. 여기서 조금 이상합니다. 실제로 변수를 제거하는 동안 변수를 설정합니다. 미드 스트립으로 설정 한 새로운 값을 스트립 글로 사용합니다. 알 겠어? 우리는 ##*
에서 아무것도 할 수있는 마지막 문자에 대한 우리의 증가 변수의 머리에서 모두 제거 [$((PS2c=0))-9]
. 우리는 이런 식으로 값을 출력하지 않도록 보장하지만 여전히 값을 할당합니다. 꽤 멋지다-나는 전에 그것을 한 적이 없다. 그러나 POSIX는 이것이 가장 수행하기 쉬운 방법임을 보증합니다.
POSIX 지정 덕분에 ${parameter} $((expansion))
이러한 정의를 평가하는 위치에 관계없이 별도의 하위 쉘로 설정하지 않고도 현재 쉘에 이러한 정의를 유지할 수 있습니다. 그것이 작동 이유입니다 dash
및 sh
단지뿐만 아니라 그것은에서와 같이 bash
와 zsh
. 쉘 / 터미널 종속 이스케이프를 사용하지 않고 변수 자체를 테스트 할 수 있습니다. 그것이 휴대용 코드를 빠르게 만드는 것 입니다.
나머지는 상당히 간단합니다. 매번 카운터를 다시 증가시킬 $PS2
때까지 카운터를 증가시킵니다 $PS1
. 이처럼 :
PS2='$((PS2c=PS2c+1)) > '
그래서 지금 할 수 있습니다 :
대시 데모
ENV=/tmp/prompt dash -i
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 > printf '\t%s\n' "$PS1" "$PS2" "$PS2c"
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
0
/u/s/m/man3 > cd ~
/h/mikeserv >
SH 데모
bash
또는 에서 동일하게 작동합니다 sh
.
ENV=/tmp/prompt sh -i
/h/mikeserv > cat <<HEREDOC
1 > $( echo $PS2c )
2 > $( echo $PS1 )
3 > $( echo $PS2 )
4 > HEREDOC
4
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
/h/mikeserv > echo $PS2c ; cd /
0
/ > cd /usr/share
/u/share > cd ~
/h/mikeserv > exit
위에서 말했듯이 주요 문제는 계산을 수행하는 위치를 고려해야한다는 것입니다. 부모 셸에서 상태를 얻지 못하므로 계산하지 않습니다. 서브 쉘에서 상태를 얻습니다. 그래서 계산하는 곳입니다. 그러나 부모 쉘에서 정의를 수행합니다.
ENV=/dev/fd/3 sh -i 3<<\PROMPT
ps1() { printf '$((PS2c=0)) > ' ; }
ps2() { printf '$((PS2c=PS2c+1)) > ' ; }
PS1=$(ps1)
PS2=$(ps2)
PROMPT
0 > cat <<MULTI_LINE
1 > $(echo this will be line 1)
2 > $(echo and this line 2)
3 > $(echo here is line 3)
4 > MULTI_LINE
this will be line 1
and this line 2
here is line 3
0 >
man 1 mktemp
.