마지막 명령에서 슬래시 대신 백 슬래시 대체


10

cd C:\foo\bar\PowerShell에서 Cygwin으로 명령 을 복사했으며 sillily 가 명령 을 실행할 것으로 예상했습니다. 지금은 모든 대체 할 대체를 실행하기 위해 노력하고있어 \/:

$ !!:gs/\\/\/
bash: :gs/\\/\/: substitution failed

대체가 실패한 이유를 잘 모르겠습니다.

나는 또한 시도했다 :

$ !!:gs/\\/q

교체가 문제인지 확인하십시오. 그렇지 않습니다. 이제 궁금하다!

"대체 실패"가 표시되는 이유는 무엇입니까?


2
지금 당장 cygwin이 없지만 Windows 경로가 작동한다고 생각했습니다 ... 논쟁을 인용하려고 시도 했습니까? 즉cd 'C:\foo\bar'
mpy

@mpy 이것은 실제로 작동합니다! 내가 대체를 고집하지 않았다는 것을 몰랐다.
Tanner Faulkner

1
"zsh를 사용하여 답변을받을 수 있습니다." 당신의 원본 !!:gs/\\/\/은 zsh에서 작동합니다…
Kamil Maciorowski

@TannerFaulkner fc -s '\'='/' -1는 Ubuntu LTS 기본 bash에서 작동합니다. Cygwin에서도 작동하는지 알려주세요. 답변에 더 많은 단어를 게시했습니다.
Hastur

1
여기서 일반적인 bash 동작은 대체가 발생하기 전에 백 슬래시가 이스케이프 처리되는 것입니다 !!:gs/\\/\//. @Hastur fc -s '\'='/' -1는 예상되는 동작을 얻습니다. 이것은 bash의 버그 일 수 있습니다.
quixotic

답변:


6

슬래시도 대체 명령의 분리 문자이므로 대체를 조기에 종료하지 않도록 대체 문자열로 이스케이프해야합니다.

!!:gs/\\/\//

또는 슬래시 이외의 것을 구분 기호로 사용하여 주석에서 제안 된 것처럼 더 명확하게

!!:gs|\\|/|

그러나 이것은 tcsh(내가 일반적으로 할당 된 쉘) 에서만 작동 bash하는 것처럼 보입니다. 이스케이프가 첫 번째 인수에서 작동하지 않는 것처럼 명령을 작동시킬 수 없습니다:s


기쁨 없음 :( 같은 오류 i.imgur.com/QFQR0xF.png
Tanner Faulkner

1
단지 말 : !!:gs|\\|/조금 더 읽기 쉬울 수 있습니다.
mpy

1
나는 그것을 bash에서 작동시킬 수 없었다. 첫 번째 인수 :s는 실제 정규 표현식으로 보이지
않습니다

4

짧은 대답 : 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 버전 코드와 같은 코드를 볼 수 있어야합니다 (그러나 위의 명령이 수행하려고하는 것을 얻었습니다 ... 그래서 나는 게으 릅니다 ....).

몇 가지 참고 사항 :

  1. 우리는 그것이 작동하는 각 RegEx를 사용할 것이라고 생각 sed하지만, 보장되지는 않습니다. 백 슬래시는 확장의 이스케이프 문자이며 문제가 있습니다. 또한 확장 동작은 shopt옵션 과 관련이 있으므로 사례별로보아야합니다.

  2. cd C:\Foo\Barbash 쉘에 문자열을 붙여 넣으면 확장되어 인터프리터에 다음과 같이 나타납니다 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역사 수정이 (아직)하지 않았다의 대체 처리 \진정한 정규식으로 문자를. ..


2

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

안녕 해리 내 GNU bash 버전 4.3.11 (1) A=$(echo "!!\\" | sed 's,\\,/,g');eval $A에서 명령이 백 슬래시로 종료되면 작동하지 않습니다. 당신이 C:\Foo\Bar\ 말했듯이, 쉘은 줄의 연속을 기다릴 것입니다. Enter를 두 번 누를 수도 있습니다. 첫 번째 경우 C:/Foo/Bar /( /; 앞에 공백이 있으면 두 번째에서는 오류가 발생합니다.이 기능은 정상적으로 작동합니다.
Hastur

나는 (1) 사용하기가 훨씬 쉽고 (2) 하나의 라이너가 구현에 의존하는 것처럼 보였기 때문에 함수를 작성했습니다.
harrymc

-1

나는 당신이 이것을 할 수 있다고 생각하지 않습니다. 다시 복사 / 붙여 넣기해야합니다.

대체 명령은 구분 기호를 허용하므로이 문제는 대체 명령 구분 기호도 슬래시와 관련이 없습니다. 이 문제는 대체 될 백 슬래시에 관한 것인데, 이미 오른쪽에 쓸모없는 간단한 문자 탈출로 간주되어왔다.

따라서 대체 명령을 호출하면 소스에서 백 슬래시가 이미 사라집니다. 명령을 그대로 ( !!) 다시 불러 오십시오 . 를 포함하여 정확히 동일한 명령을 인쇄하는 대신 c:\foo명령에서 이미 처리 된 백 슬래시를 뺀 명령을 실행합니다 c:foo.

그리고 분명히 누락 된 문자를 찾거나 바꿀 수 없습니다. 이렇게하면 오류가 발생합니다.


1
잘. 이 테스트가 실제로 작동하기 때문에 마지막으로 잘못 echo c:\Foo되었습니다 !!:gs,F,\\f,. 그러나 백 슬래시 이스케이프 자체를 대체하는 것은 고통스러운 것 같습니다.
A. Loiseau
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.