bash
수정 중인 명령을 실행하지 않는데도 기록이 변경되는 이유는 무엇 입니까? 예를 들어, 다음을 입력하면:
$ echo foo1
foo1
$ echo foo2
foo2
$ echo foo3
foo3
up그 후 두 번 누르면 echo foo2
프롬프트가 나타납니다. 나는 누르고 2를 얻습니다 echo foo22
. 이제 끝(빈 줄)으로 돌아갑니다 downdown. 지금 기록을 검색해 보면 echo foo22
명령을 실행한 적이 없는데도 알 수 있습니다!
그러나 쉘을 종료하고 다른 쉘을 열면 원래 실행된 명령이 표시됩니다. 나는 이 모든 것이 매우 혼란스럽고 직관에 어긋나며 짜증스럽다고 생각합니다.
나는 역사 작업이 다음과 같이 작동하기를 원합니다.
실제로 실행된 명령만 이력에 저장됩니다.
역사는 불변입니다. (명시적으로 지우지 않는 한.)
이를 수행할 수 있는 방법이 있습니까?
편집 - 이 질문은 관련이 있는 것 같습니다.Bash 기록 수정을 취소할 수 있는 방법이 있습니까?
답변1
나는 이 모든 것이 매우 혼란스럽고 직관에 어긋나며 짜증스럽다고 생각합니다.
이것은 귀하의 의견입니다. 각 기록 행을 편집할 수 있을 뿐만 아니라 자체적인 실행 취소 기록을 갖는 프로그래밍 언어에 대한 대화형 REPL을 구현했습니다. 따라서 한 번도 실행되지 않은 명령이 있을 수 있지만 위쪽 화살표를 사용하여 해당 명령으로 돌아가서 원래 상태로 되돌릴 수 있습니다.
하지만,배쉬에서와 마찬가지로기록 편집 내용은 수정된 줄에서 벗어나 탐색할 때만 기록에 저장됩니다. 줄을 편집한 다음 해당 줄에서 벗어나지 않고 새 명령으로 다시 제출하면 안 됩니다! 이 특별한 경우 편집 내용은 새 기록 항목으로 저장되므로 기록에 저장되지 않습니다.
여기에는 패턴과 이유가 있습니다!
새로운 명령으로 제출하기 전에 히스토리 라인의 편집을 허용하지 않는 것은 명백히 반직관적이고 성가신 일입니다.
히스토리 라인을 떠나 다른 라인을 보는 경우 히스토리 라인에 대한 편집 내용을 잃어버리는 것은 직관에 어긋나고 성가신 일입니다.
가능한 해결 방법은 다음과 같습니다. 사용자가 기록 행을 편집할 때 제출할 새 행을 나타내는 준비 영역에 저장합니다(기록을 업데이트하지 않음). 하지만:
이것은 여전히 직관에 반하고 분노를 자아냅니다. 사용자는 행을 편집할 수 없으며 이전 행을 보려면 위쪽 화살표를 두 번 누르고 편집으로 돌아가려면 아래쪽 화살표를 두 번 누릅니다. 그러면 사용자는 편집되지 않은 원본 줄을 볼 수 있으며 현재("기록 0") 편집 버퍼에서 줄의 새 버전을 찾으려면 기록 앞쪽까지 탐색해야 합니다.
사용자가 두 개의 서로 다른 기록 줄에서 두 개의 편집을 수행했다면 어떻게 될까요? 최근의 그러한 편집 내용이 최신 편집 내용에 의해 조용히 훼손된다면 짜증나는 일이 될 것입니다.
불변의 기록을 갖는 유일한 방법은 동시에 여러 개의 임시 편집을 수행하고 순서에 관계없이 새 명령으로 제출할 수 있다는 것입니다. 그러나 이 접근 방식은 혼동을 일으키지 않고 현재 UI 패러다임에 제시하기 어려울 수 있습니다. "현재 UI 패러다임"은 사용자의 위치와 상태에 대한 시각적 단서(있는 경우)가 있는 화면의 단일 편집 창에 매핑된 전체 작업 공간(기록 및 새 항목)입니다.
해당 기록 행에 임시 수정 사항이 포함되어 있는지 여부를 나타내는 위치 표시기(사용자에게 기록 공간의 위치를 나타내는 작은 숫자)가 필요할 수 있습니다. 변경 사항을 영구적으로 적용(변경 내역), 행이나 일련의 행 또는 모든 행 등에 대한 변경 사항을 취소하는 방법
답변2
나는 이것이 성가신 기본 동작이라는 점에 동의합니다(그리고 bash
이 동작은 고유한 것 같습니다 readline
). 적어도 내 자신의 경험에 따르면, 수정된 줄을 버린다면 그것은 일반적으로 이미 해당 수정 사항을 버렸기 때문에 원래 줄을 잃기보다는 차라리 버리는 편이 낫습니다!
해당 행 수정을 포기한 이유가 먼저 다른 작업을 수행해야 했기 때문에(그것이 해당 작업을 수행한 원래 이유였을 수 있음) 해당 수정 사항을 그대로 두는 것이 유용할 수 있습니다. 그러나 제 생각에는 이전에 수행된 작업에 대한 증거를 잃기 때문에 원래 기록 항목을 덮어쓰는 것은 좋지 않습니다.
가장 짜증나는 시나리오는 새 명령을 다시 시작하기 위해 전체 줄을 지운 다음 승인한 다른 줄로 이동하고 나중에 기록 항목이 사라진 것 같다는 것을 깨닫는 것입니다.
또한, 수정 사항을 유지하려는 경우에도 수정된 행으로 돌아가려면 다시 검색해야 합니다.
IMO 동작이 zsh
더 유용합니다. 라인을 수락하지 않고 수정된 라인 사이를 앞뒤로 전환하는 한 전체 기록을 수정할 수 있지만 새 라인을 수락하자마자 기록에 추가되지만 이전 기록 라인은 유지됩니다(누르는 동안 Ctrl+C기록에 새 행을 추가하지 않고 모든 수정 사항을 취소함).
다른 행에 대한 수정 사항을 저장하려면 해당 행을 대기열에 저장하거나 Alt+Q(다음 프롬프트에서 대기열의 맨 위를 자동으로 가져옴)살인 반지그리고 Ctrl+U.
다행히도 bash
/ 에서는 readline
다음을 사용하여 동작을 변경할 수 있습니다.
bind 'set revert-all-at-newline on'
(또는 set revert-all-at-newline on
readline ~/.inputrc
을 사용하는 모든 응용 프로그램에서 작동합니다).
그러면 에서와 유사한 동작이 발생합니다 yash
. 이는 와 동일 zsh
하지만잡다대기열(그러나 여전히 사용할 수 있습니다.살인 반지( Ctrl+Y, Alt+Y)를 이용하여 당깁니다.
답변3
기본적으로 readline 및 readline 함수를 ↑각각 누르고 호출합니다 .↓previous-history
next-history
이 기능을 사용하면 기록에서 줄을 가져오고 기록을 편집할 수 있습니다.
↑바인딩하고 ↓바인딩 하면 기록을 편집할 위험 없이 유사한 동작이 발생합니다 history-search-backward
.history-search-forward
이렇게 하려면 다음을 추가하세요 ~/.inputrc
.
# Press up-arrow for previous matching command
"\e[A":history-search-backward
# Press down-arrow for next matching command
"\e[B":history-search-forward
또는 다음 항목에 추가하세요 ~/.bashrc
.
# Press up-arrow for previous matching command
bind '"\e[A":history-search-backward'
# Press down-arrow for next matching command
bind '"\e[B":history-search-forward'
이로 인해 접근 방식 ↑과 ↓작업 방식이 약간 변경됩니다.
명령줄이 비어 있으면 동작은 원래 기능과 동일합니다. 기록을 통해 표준 한 단계씩 실행을 수행할 수 있습니다(기록 편집이 없는 경우).
무언가를 입력한 후 를 누르면 ↑bash는 입력한 내용을 접두어로 처리하고 기록에 일치하는 명령만 표시합니다.
예를 들어, 입력 git
하고 누르면 ↑기록에 로 시작하는 명령이 표시됩니다 git
. ↑빈 명령줄을 누르면 모든 명령이 표시됩니다.