.bash_history
PROMPT_COMMAND
다음 설정을 사용하여 모든 터미널 탭과 창에서 명령 기록을 활성화 하고 싶습니다 .profile
.
export PROMPT_COMMAND="history -a; history -c; history -r;$PROMPT_COMMAND"
그러나 이 환경 변수가 설정되어 있는지 확인하면 다음과 같은 결과가 나타납니다.
echo $PROMPT_COMMAND
printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"
PROMPT_COMMAND
이렇게 내보내면 기존 목록을 덮어쓰게 됩니까 , 아니면 내보내기 전에 값 앞에 접두사를 붙여야 $PROMPT_COMMAND
합니까 ?PROMPT_COMMAND
:
답변1
Google 검색 시 상위 결과 중 하나인 "PROMPT_COMMAND seperator"
이 답변은 지금까지 제공된 것보다 더 많은 노력을 기울일 가치가 있다고 생각합니다.
노트:이 게시물을 준비하면서 Bash 버전 3.2, 4.4, 5.0 및 5.1을 테스트했습니다.도커) 동일한 버전의 소스 코드를 확인했습니다.gnu.org)
시작하자...
배쉬 매뉴얼
배쉬 <= v5.0
PROMPT_COMMAND 변수의 값은 이전에 확인됩니다. Bash는 각 주요 프롬프트를 인쇄합니다. PROMPT_COMMAND가 설정되어 있고 null이 아닌 값이 있으면 마치 null이 아닌 것처럼 값을 실행합니다. 이미 명령줄에 입력되었습니다.
무슨 뜻이에요?
즉, bash는 다음과 거의 동일한 작업을 수행합니다.
eval "${PROMPT_COMMAND:-}"
따라서 이 목적에 적합한 명령의 연결/순서는 eval
허용됩니다.
배쉬 >= v5.1
Bash는 배열 변수 PROMPT_COMMAND의 값을 확인합니다. 각 주요 팁을 인쇄하기 직전. PROMPT_COMMAND의 요소가 설정되어 있고 비어 있지 않으면 Bash 이미 실행된 것처럼 각 값을 번호순으로 실행합니다. 명령줄에 입력하세요. ... 이 변수가 설정되고 배열인 경우 각 변수의 값은 set 요소는 실행될 명령으로 해석됩니다. 메인 프롬프트($PS1)를 인쇄하기 전. 설정되었지만 배열 변수가 아닌 경우 해당 값이 사용됩니다. 실행될 명령으로.
무슨 뜻이에요?
즉, bash는 다음과 거의 동일한 작업을 수행합니다.
if [[ ${#PROMPT_COMMAND[@]} -gt 1 ]]; then
for cmd in "${PROMPT_COMMAND[@]}"; do eval "${cmd:-}"; done
else
eval "${PROMPT_COMMAND:-}"
fi
즉, 배열의 각 요소는 eval
독립적 입니다.
커뮤니티는 무엇을 하고 있나요?
수색"PROMPT_COMMAND"
github에 표시됨:
- 일반적으로 커뮤니티에서는
;
구분 기호로 사용합니다. - 경우에 따라
$'\n'
구분 기호 로 사용됨
내가 구체적으로 본 것은
몇 가지 일화 참고 사항:
- Mac OSX 사용
;
( 참조/etc/bashrc_Apple_Terminal
) - Bash 사전 실행 나타나다사용
$'\n'
- 꽝 닫아사용
;
실제로 작동하는 모습을 봅시다
먼저 새로운 Bash v3.2 환경을 구축해 보겠습니다.
docker run -it --rm bash:3.2
bash-3.2$
세미콜론으로 구분된 문자열
-로 구분된 문자열을 사용하여 테스트하면 ;
다음이 생성됩니다.
bash-3.2$ PROMPT_COMMAND='printf 1;printf 2;printf 3;printf ":\n"'
123:
bash-3.2$
줄로 구분된 문자열
-로 구분된 문자열을 사용하여 이 결과를 테스트합니다 \n
.
bash-3.2$ PROMPT_COMMAND=$'printf 1\nprintf 2\nprintf 3\nprintf ":\n"'
123:
bash-3.2$
둘 다 섞는다
두 구분 기호를 모두 혼합할 수 있나요? 옙! :
bash-3.2$ PROMPT_COMMAND=$'printf 1;printf 2\nprintf 3;printf ":\n"'
123:
bash-3.2$
배열은 어떻습니까?
우리가 가는 곳에서는 Bash v5.1이 필요합니다.
docker run -it --rm bash:5.1
bash-5.1$
리터럴 배열
리터럴 배열을 사용하여 이 결과를 테스트합니다.
bash-5.1$ PROMPT_COMMAND=( "printf 1" "printf 2" "printf 3" "printf ':\n'" )
123:
bash-5.1$
세 가지 모두 사용해보세요!
모두 섞으면 어떻게 될까요?
bash-5.1$ PROMPT_COMMAND=( "printf 1" $'printf 2\nprintf 3' 'printf 4;printf ":\n"' )
1234:
bash-5.1$
어느 것을 사용할 것인가?
${PROMPT_COMMAND}
배열인 경우 배열에 명령을 추가/추가해야 합니다 .
참고 원하는 경우 명령 그룹(예: 단일 ;
또는 $'\n'
구분된 명령 문자열)을 배열에 개별 항목으로 추가할 수 있습니다.
${PROMPT_COMMAND}
배열이 아닌 경우 다음을 수행해야 합니다.아마도;
좀 더 공식적인 구분 기호처럼 느껴지므로 명령을 추가할 때 사용하세요 . 하지만 추가하는 명령은 $'\n
'.'으로 구분된 단계를 포함할 수 있는 더 복잡한 스크립트일 수 있다는 점에 유의하세요.
씹기 기능을 사용해 볼까요?
틀림없이!
##
# pc_munge munges PROMPT_COMMAND.
# Tries to accommodate when PROMPT_COMMAND is an array (supported in Bash v5.1+).
# If ${#PROMPT_COMMAND[@]} has 2+ elements, then we treat as an array, otherwise
# we defensively treat it as a string.
# By default, uses ';' as separator.
#
# NOTE: Does NOT check if command is already present
#
# Parms:
# $1 command to add
# $2 before | after (default: after)
# $3 separator (default: ';')
#
pc_munge() {
[[ -n "$1" ]] || return
local fs="${3:-;}" # null | '' => default
case "${2:-after}" in
before)
[[ ${#PROMPT_COMMAND[@]} -gt 1 ]] && PROMPT_COMMAND=( "$1" "${PROMPT_COMMAND[@]}" ) || PROMPT_COMMAND="${1}${PROMPT_COMMAND:+${fs}$PROMPT_COMMAND}"
;;
*) # after
[[ ${#PROMPT_COMMAND[@]} -gt 1 ]] && PROMPT_COMMAND+=( "$1" ) || PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND${fs}}${1}"
;;
esac
}
[편집: 철자 오류 "PROMP_" => "PROMPT_"]
[편집: 오타 "Som" => "일부"]
[편집: "노래하다" 철자 오류 => "싱글"]
답변2
$PROMPT_COMMAND는 콜론으로 구분된 목록입니까?
테스트하기 쉽습니다.
$ PROMPT_COMMAND='true:true' bash
bash: true:true: command not found
$ exit
따라서 대답은 "아니요"입니다.
하지만 당신은 그것을 다음과 같이 생각할 수 있습니다세미콜론다른 쉘 코드 행과 마찬가지로 구분된 명령 시퀀스:
$ PROMPT_COMMAND='echo x;echo y' bash
x
y
$ exit
귀하의 질문에 있는 작업에는 세미콜론으로 구분된 여러 명령이 있고 PROMPT_COMMAND
끝에 이전 값이 추가되어 있습니다.
물론 PROMPT_COMMAND
여러 명령을 실행하는 또 다른 방법은 함수를 만들고 거기에서 호출하는 것입니다.
즉, 두 가지 이유로 printf
시퀀스가 실제 프롬프트에 더 잘 배치되어 보일 수 있습니다. PROMPT_COMMAND
첫째, 개행 문자로 끝나지 않기 때문에 종료하기 전에 불완전한 줄을 출력하는 다른 명령처럼 커서 위치에 대한 Bash의 이해를 망칠 수 있습니다. 둘째, 탭 완성을 통해 쉘에 프롬프트를 다시 인쇄하도록 요청하면 PS1
프롬프트가 다시 표시되지만 PROMPT_COMMAND
다시 실행되지는 않습니다.
답변3
bash $PROMPT_COMMAND
(또는 @DavidFarrell이 이미 지적한 대로 bash 5.1+의 배열인 경우 각 요소)는 쉘 코드로 해석되므로 해당 내용을 쉘 스크립트처럼 작성할 수 있습니다. 쉘 스크립트에서 명령은 ;
, newline
, |
, &
, &&
등 으로 구분할 수 있습니다. ||
각 명령은 고유한 의미를 갖습니다.
예를 들면 다음과 같습니다.
PROMPT_COMMAND='
cmd1 && cmd2 &
cmd3; cmd4
for cmd in cmd5 cmd6; do
"$cmd"
done
cmd7 << "EOF"
foo bar
EOF'
등.
이미 설정된 명령에 명령을 추가 $PROMPT_COMMAND
하고 이전 명령과 독립적으로 실행되도록 하려면 다음을 선택 ;
하고새로운 팀, 그러나 처음에 비어 있거나 이 문서 구분 기호(위의 것과 같은)로 끝나는 특수한 경우에는 작동하지 않습니다 ;
.$PROMPT_COMMAND
EOF
PROMPT_COMMAND+='
your extra command here'
(또는 이전 버전의 경우:
PROMPT_COMMAND=$PROMPT_COMMAND'
your extra command here'
)
선호됩니다. 또는:
PROMPT_COMMAND='your extra command here
'$PROMPT_COMMAND
먼저 실행되도록 미리 추가하세요.
Bash 5.1+에서는 배열 요소를 추가할 수도 있습니다.
PROMPT_COMMAND+=(
'your extra command here'
)
아니면 앞에 추가하세요:
PROMPT_COMMAND=(
'your extra command here'
"${PROMPT_COMMAND[@]}"
)
이는 잠재적인 문제를 남깁니다. errexit
( -e
) 옵션이 활성화되어 있고 이러한 스크립트의 명령이 실패하면 처리가 중지되므로 추가 명령이 실행되지 않을 수 있습니다. 하지만 이는 아마도 병적인 사례로 보아야 할 것입니다. 아마도 대화형 쉘에서 사용하는 것은 errexit
좋지 않은 생각일 것입니다 (스크립트에서 사용될 때 이미 논란의 여지가 있습니다).
비교를 위해 에서는 zsh
대신 $PROMPT_COMMAND
유사한 이름에서 영감을 받은(및 개선된) 다른 지점에서 호출되는 후크 함수가 있습니다.특별한 별칭존재하다 tcsh
. precmd()
각 프롬프트 전에 호출되도록 정의하려는 함수입니다. 에서는 호출할 추가 함수가 포함된 특수 배열을 설정할 zsh
수도 있습니다 ( 처리에도 영향을 미침).precmd_functions
errexit
nounset
¹처리 중에 구문 오류나 치명적인 오류가 발생하는 경우 이 옵션에서도 동일한 현상이 발생할 수 있습니다.