PROMPT_COMMAND에서 마지막 명령이 비어 있는지 확인


12

bash에서 PROMPT_COMMAND 내부에서 사용자가 'return'을 누르고 명령을 입력하지 않았는지 알 수있는 방법이 있습니까?

답변:


7

히스토리 번호가 증가했는지 확인하십시오. 취소 된 프롬프트 또는 사용자가 방금 누른 프롬프트 Enter는 기록 번호를 증가시키지 않습니다.

히스토리 번호는 변수에서 사용할 수 HISTCMD있지만 사용할 수는 없습니다 PROMPT_COMMAND(실제로 이전 명령의 히스토리 번호가 있기 때문에 PROMPT_COMMAND자신 을 실행하는 명령 에는 히스토리 번호가 없습니다). 의 출력에서 ​​숫자를 얻을 수 있습니다 fc.

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

히스토리 ( HISTCONTROL=ignoredups또는 HISTCONTROL=erasedups) 에서 중복 스쿼시를 설정 한 경우 두 개의 동일한 명령을 연속적으로 실행 한 후 빈 명령이 잘못보고됩니다.


고마워, 질 여기에 뭔가 빠졌습니다. 리터럴 함수의 첫 번째 줄에 'echo hello'를 넣는 것은 작동하지 않지만 PROMPT_COMMAND = 'echo hello'는 작동하지 않으므로 실행되지 않는 것 같습니다. 나는 그것이 HISTCMD_previous vs HISTCMD_PREVIOUS 문제 일지 모르지만 주사위는 없다고 생각했습니다. 나는 계속 파고 있지만, 당신의 bash fu가 분명히 내 리그를 넘어서고 있다고 언급하고 있습니다.
사용자

@ user 더 많은 오타를 수정했습니다. 특히 ${HISTCMD_previous%%$'[\t ]'*}비트가 누락되어 탭이나 공백 대신 t 또는 공백 $'…'후에 잘 `, 립니다. 그러나 bash는 탭을 인쇄합니다.
Gilles 'SO- 악 그만

1
이 솔루션은 중복이 기록에 저장된다는 가정을 기반으로합니다 (OFF). 따라서이 솔루션은 반복 명령에 대해 예상대로 작동하지 않지만 복제본은 기록에 저장되지 않습니다.
schlimmchen

4

해결 방법이 있지만 몇 가지 요구 사항이 있습니다.

$HISTCONTROL모든 명령, 중복 및 공백을 저장 하도록 설정해야 합니다. 그래서 설정 :

HISTCONTROL=

이제 호출 할 함수를 다음과 같이 정의하십시오 $PROMPT_COMMAND.

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

이제 $PROMPT_COMMAND변수를 설정하십시오 .

PROMPT_COMMAND="isnewline"

출력을보십시오 :

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

여기서 임시 파일을 사용하는 이유를 모르겠습니다. 변수 last는 한 번의 호출 isnewline에서 다음 호출로 유지됩니다 ( prompt_command__isnewline__last충돌을 피하기 위해 덜 일반적인 이름 만 선택하십시오 ).
Gilles 'SO- 악마 그만'

@Gilles 당신이 맞아요, 난 당신의 제안에 감사드립니다
혼란

고마워요 다음과 같은 아이디어를 사용했는데 구문 분석이 조금 더 쉽습니다. HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
사용자

1

나는 그 자체 를 수행하는 방법을 모른다 . 그러나 다음을 사용하여 동일한 효과를 얻을 수 있습니다

트랩 some_command_or_function 디버그

이렇게하면 some_command_or_function명령을 실행할 때마다가 호출됩니다. 까다로운 점은 EnterPROMPT_COMMAND가 정의되어 있지 않는 한 방금 눌렀을 때 호출되지 않습니다 Enter.

원하는 결과를 얻는 가장 간단한 방법은 PROMPT_COMMAND를 사용하는 대신 디버그 트랩 함수를 정의하는 것입니다. 그러나 나는 당신이 원하는 결과를 모르기 때문에 말할 수 없습니다. 방금 눌렀을 때 Enter어떤 일이 발생하고 명령을 입력 할 때 다른 / 추가적인 일이 발생하려면 (AFAIK) 디버그 트랩과 PROMPT_COMMAND를 사용해야합니다. 참조 이 답변 하고  이 한 두 가지 메커니즘을 멋지게 함께 플레이 할 수있는 방법에 대한합니다.


0

(이것은 내가 의견을 추가 할 수 있다면 허용 된 답변에 대한 의견 일 것입니다 ...) @schlimmen, 당신은 HISTTIMEFORMAT같은 것으로 설정 HISTTIMEFORMAT='%F %T '한 다음 저장하고 비교할 수 history 1있습니다. 소거를 사용하면 매번 마지막 명령 의 타임 스탬프 ( 매번 반복 될 수 있음)가 매번 변경되고 HISSTIMEFORMAT적절하게 설정되면 history 1타임 스탬프 (와 달리 fc) 가 표시 되므로 반복되는 명령 간에도 차이가 있기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.