cd C:\foo\bar\
PowerShell에서 Cygwin으로 명령 을 복사했으며 sillily 가 명령 을 실행할 것으로 예상했습니다. 지금은 모든 대체 할 대체를 실행하기 위해 노력하고있어 \
와 /
:
$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed
대체가 실패한 이유를 잘 모르겠습니다.
나는 또한 시도했다 :
$ !!:gs/\\/q
교체가 문제인지 확인하십시오. 그렇지 않습니다. 이제 궁금하다!
“대체 실패”가 표시되는 이유는 무엇입니까?
답변
슬래시도 대체 명령의 분리 문자이므로 대체를 조기에 종료하지 않도록 대체 문자열로 이스케이프해야합니다.
!!:gs/\\/\//
또는 슬래시 이외의 것을 구분 기호로 사용하여 주석에서 제안 된 것처럼 더 명확하게
!!:gs|\\|/|
그러나 이것은 tcsh
(내가 일반적으로 할당 된 쉘) 에서만 작동 bash
하는 것처럼 보입니다. 이스케이프가 첫 번째 인수에서 작동하지 않는 것처럼 명령을 작동시킬 수 없습니다:s
답변
짧은 대답 : bash 의 내장 fc
(수정 명령)
fc
명령이며, 내장 된 역사의 명령을 편집 및 다시 실행하기 위해 만든 bash 쉘에서이.
그것은이다 너무 Cygwin에서에있는 그리고 내가 테스트하는 모든 리눅스 배포판에서 작동합니다 :
fc -s '\'='/' -1
몇 가지 설명
fc
히스토리 목록 에서 명령 을 나열하거나 편집하고 다시 실행하기 위한 bash 내장 명령 입니다.-1
역사에서 마지막 명령을 취할 것입니다. 짝수!!
는 다음man bash
과 같이 정의됩니다 (에서 읽음 ).
!! Refer to the previous command. This is a synonym for
! -1 ‘.-
-s
패턴을 다른 것으로 대체합니다. 이번에는help fc
(내장 명령이므로help
) :`fc -s [pat = rep …] [command] ‘형식으로, OLD = NEW 대체가 수행 된 후 COMMAND가 다시 실행됩니다.
좋아,
pat=rep
대신에OLD=NEW
… - 셸에서 패턴을 읽으므로 인용 부호로 보호해야합니다 :
'\'
및'/'
.
왜 “대체 실패”를 받고 있는지에 대한 몇 마디
s
수정자가 백 슬래시 문자의 대체 (아직)를 구현하지 않은 것 같습니다 \
. 이스케이프 문자 입니다. bash 기록 확장의 gnu 버전 코드와 같은 코드를 볼 수 있어야합니다 (그러나 위의 명령이 수행하려고하는 것을 얻었습니다 … 그래서 나는 게으 릅니다 ….).
몇 가지 참고 사항 :
-
우리는 그것이 작동하는 각 RegEx를 사용할 것이라고 생각
sed
하지만, 보장되지는 않습니다. 백 슬래시는 확장의 이스케이프 문자이며 문제가 있습니다. 또한 확장 동작은shopt
옵션 과 관련이 있으므로 사례별로보아야합니다. -
cd C:\Foo\Bar
bash 쉘에 문자열을 붙여 넣으면 확장되어 인터프리터에 다음과 같이 나타납니다cd C:FooBar
. 이 형식으로$_
내부 변수에도 저장됩니다 .
대신 붙여 넣을 경우,cd "C:\Foo\Bar"
또는cd 'C:\Foo\Bar'
에$_
변수 당신이 찾아야한다C:\Foo\Bar
.
전체 행을 읽은 직후 히스토리 확장이 수행되기 때문에 쉘이 단어를 나누기 전에 약간의 bashism 을 사용하여 시작하는 경향 이있을 수 있습니다 ( 예 ::p
또는:q
,""
, 파싱 등 …)!!:0 ${_//\\/\/}
경로와 파일 이름 으로 게임 을 시작 하는 것이 안전하지 않다는 것을 기억하는 순간입니다 . 특히 파일 이 Windows 클립 보드에서 온 경우 (일반적으로 구문 분석 하지 않는 이유는 무엇 입니까?
ls
페이지를 읽으 십시오. 파일 이름과 디렉토리 이름에 대한 올바른 문자로 공백과 줄 바꿈 …).
또한 마우스로 캡처 한 텍스트 를 붙여 넣으면 선행 공백도 붙여 넣을 수 있습니다. 이것은 명령이 기록에서 끝나는 것을 피할 수 있습니다 (쉘 옵션에 따라 다릅니다 …). 그렇다면 다음!!
은 통제되지 않는 명령입니다 … ( 다른 답변 의 예 참조 ).이것은 불필요한 유형의 위험 입니다.
결론
히스토리 확장 은 히스토리 목록의 단어를 입력 스트림에 도입하여 명령을 쉽게 반복하고, 이전 명령의 인수를 현재 입력 행에 삽입하거나, 이전 명령의 오류를 빠르게 수정합니다.
쉽지 않다면 우리가 잘못하고 있다고 생각하기 시작합니다. ;-)
광고 구역 : 작은 실험
histverify
셸에서 활성화 했습니다 …
shopt -s histverify
echo C:\Foo\Bar
!!:s|C|D| {1,2}A
그때 눌러 Enter과 같이 확인 확장을 나는 발견
echo D:\Foo\Bar {1,2}A
그런 다음 Enter다시 누르면 에코가 울립니다.
D:FooBar 1A 2A
이것은이 있음을 나타내는 것 같다 substitution failed
의 전에 처리 역사 확장에 생성되는 중괄호 확장 , 그래서 무엇보다도 먼저 , 그리고 확인하는 것 s
역사 수정이 (아직)하지 않았다의 대체 처리 \
진정한 정규식으로 문자를. ..
답변
sed
결과를 대체하고 실행하는 데 사용할 수 있습니다 .
이러한 명령에 대해 몇 가지 가능한 변형이 있지만 내 배쉬에서는이 명령 만 작동했습니다.
A=$(echo "!!\\" | sed 's,\\,/,g');eval $A
는 \\
에 추가됩니다 !!
마지막 명령은 백 슬래시로 끝날 경우입니다. 그것이 없으면 껍질이 혼란스러워 줄이 계속되도록 요구합니다.
파일에서 이것을 bash 함수로 추가 할 수도 있습니다 ~/.bashrc
.
function slash {
A=$(history | tail -n 2 | head -n 1 | cut -c 8- | sed 's,\\,/,g')
eval $A
}
다음은 Windows의 Bash에서 작동하는 방법입니다.
A=
명령이 쉘 변수에 올바른 값을 지정 하는 방법을 설명하려면 다음을 수행하십시오 A
.
tail
라인의 제공 명령 과거로부터 마지막 두 라인을 얻어cd \mnt\c
다음을slash
자체. 의 일부history | tail -n 2
는로도 쓰일 수 있습니다history 2
.head
첫 줄을 가져 가라cd \mnt\c
cut
공급 한 라인 번호를 잘라냅니다.history
sed
모든 슬래시를 슬래시로 대체eval
변수의 내용을 실행A
답변
나는 당신이 이것을 할 수 있다고 생각하지 않습니다. 다시 복사 / 붙여 넣기해야합니다.
대체 명령은 구분 기호를 허용하므로이 문제는 대체 명령 구분 기호도 슬래시와 관련이 없습니다. 이 문제는 대체 될 백 슬래시에 관한 것인데, 이미 오른쪽에 쓸모없는 간단한 문자 탈출로 간주되어왔다.
따라서 대체 명령을 호출하면 소스에서 백 슬래시가 이미 사라집니다. 명령을 그대로 ( !!
) 다시 불러 오십시오 . 를 포함하여 정확히 동일한 명령을 인쇄하는 대신 c:\foo
명령에서 이미 처리 된 백 슬래시를 뺀 명령을 실행합니다 c:foo
.
그리고 분명히 누락 된 문자를 찾거나 바꿀 수 없습니다. 이렇게하면 오류가 발생합니다.