명령 행에서 정규식 백 슬래시를 이스케이프 처리하는 데 필요한 백 슬래시 수


12

최근에 명령 줄에서 일부 정규 표현식에 문제가 있었고 백 슬래시를 일치시키기 위해 다른 수의 문자를 사용할 수 있음을 발견했습니다. 이 숫자는 정규식에 사용 된 따옴표 (없음, 작은 따옴표, 큰 따옴표)에 따라 다릅니다. 의미하는 바는 다음 bash 세션을 참조하십시오.

echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file

이것은 다음을 의미합니다.

  • 따옴표없이 4-7 실제 백 슬래시와 백 슬래시를 일치시킬 수 있습니다
  • 큰 따옴표로 백 슬래시를 3-6 실제 백 슬래시와 일치시킬 수 있습니다
  • 작은 따옴표를 사용하면 백 슬래시를 2-3 실제 백 슬래시와 일치시킬 수 있습니다

쉘에서 bash 맨 페이지의 추가 백 슬래시가 무시된다는 것을 이해합니다.

"인용되지 않은 백 슬래시 (\)는 이스케이프 문자입니다. 다음에 오는 다음 문자의 리터럴 값을 유지합니다."

작은 따옴표로 이스케이프 처리되지 않으므로 작은 따옴표로 묶인 예제에는 적용되지 않습니다.

그리고 grep 명령에 의해 하나의 추가 백 슬래시는 무시됩니다 ( "\ c"는 "c"이스케이프되지만 "c"는 정규식에서 특별한 의미를 갖지 않기 때문에 "c"와 동일합니다)).

이것은 작은 따옴표로 예제의 동작을 설명하지만 다른 두 예제, 특히 qouted가 아닌 큰 따옴표로 묶인 문자열 사이에 차이점이있는 이유를 이해하지 못합니다.

bash 매뉴얼 페이지에서 인용 한 내용은

"큰 따옴표로 문자를 묶으면 $,`, \ 및 히스토리 확장이 활성화 된 경우를 제외하고 따옴표 안에있는 모든 문자의 리터럴 값이 유지됩니다!"

GNU awk (예 :)로 awk /ab\cd/{print} file동일한 결과를 얻었습니다.

그러나 Perl은 다른 결과를 보여줍니다 (예 :) perl -ne "/ab\\cd/"\&\&print file.

  • 따옴표없이 4-5 실제 ​​백 슬래시와 백 슬래시를 일치시킬 수 있습니다
  • 큰 따옴표로 백 슬래시를 3-4 실제 백 슬래시와 일치시킬 수 있습니다
  • 작은 따옴표로 백 슬래시를 2 개의 실제 백 슬래시와 일치시킬 수 있습니다

grep과 awk에 대한 명령 줄에서 인용되지 않은 것과 이중 인용 된 정규 표현식 문자열의 차이점을 누구나 설명 할 수 있습니까? 나는 보통 Perl one-liner를 사용하지 않기 때문에 Perl의 행동에 대한 설명에 관심이 없다.

답변:


10

인용되지 않은 예제의 경우, 각 \\쌍은 하나의 백 슬래시를 grep에 전달하므로 4 개의 백 슬래시는 grep에 전달되어 단일 백 슬래시로 변환됩니다. 6 개의 백 슬래시는 3을 grep으로 전달하여 1 개의 백 슬래시와 1을 변환 \c합니다 c. 이 번역되어 있기 때문에 하나의 추가 백 슬래시, 아무것도 변경하지 않는다 \c> - c쉘. 쉘의 8 개의 백 슬래시는 grep에서 4 개이며 2 개로 변환되므로 더 이상 일치하지 않습니다.

큰 따옴표로 묶인 예를 보려면 bash 맨 페이지에서 두 번째 따옴표 뒤에 나오는 내용을 참고하십시오.

백 슬래시는 $,`, ", \ 또는 개행 문자 중 하나가 뒤에 오는 경우에만 특별한 의미를 유지합니다.

즉, 홀수의 백 슬래시를 제공하면 순서는로 끝나고 인용되지 않은 경우와 \c동일 c하지만 인용하면 백 슬래시는 특별한 의미 \c를 잃어 grep으로 전달됩니다. 따라서 "가능한"백 슬래시 범위 (예 : 파일과 일치하는 패턴을 구성하는 백 슬래시)의 범위가 하나씩 아래로 내려갑니다.


... 그리고 다음과 같은 몇 가지 이상한 점이 있습니다. exemple의 경우 : printf "\ntest""test"앞에 개행을 삽입합니다. 비록 큰 따옴표로 쉘 "\n""n"의해 변환되어야 하더라도 ... . "\ ntest는", "ntest는"우리는 쓰기에 습관을 얻어야한다 : printf "\\ntest"printf '\ntest',하지만 어떻게 든 대신 이상한에 의존하는 스크립트를 많이 참조하십시오.
올리비에 Dulac에게

6

이 링크는 bash 따옴표와 이스케이프를 설명했습니다.

귀하의 질문은 처음 세 섹션을 다룹니다.

  • 문자 별 이스케이프
  • "큰 따옴표"를 인용하는 약한
  • 강력한 인용문 '작은 따옴표'
  • 문자열 인용과 같은 ANSI C
  • I18N / L10N 인용 (국제화 및 현지화) .

아래는 문자열을 bash전달하는 grep방법과 grep내부적으로 더 해석하는 방법 에 대한 차트입니다 .

먼저 살펴 보자 echo "#ab\\cd" > file.
(가)에서 약 인용 ( "") "#ab\\cd", (가) \\인 탈출 \에 전달되는 file하나의 문자로 \. 그래서, file포함 ab\cd

이제 여러분의 명령에 따라 : 아래 차트는 각 통화에서 실제로 어떤 일이 진행되는지 확인하는 데 도움이 될 수 있습니다. 는 *파일의 내용과 일치하는 사람을 보여줍니다. 웹 페이지에서와 같이 bash의 이스케이프 규칙을 적용하는 것은 문제입니다. 다니엘 쿨만 (Daniel Kullmann)의 대답은 약한 인용 상황 에서 행동을 피하는 것을 말합니다 .

백 슬래시는 $,`, ", \ 또는 개행 문자 중 하나가 뒤에 오는 경우에만 특별한 의미를 유지합니다.


                            bash passes    grep further
                            to grep        resolves to         
grep -E ab\cd file            abcd           abcd   
grep -E ab\\cd file           ab\cd          abcd  
grep -E ab\\\cd file          ab\cd          abcd
grep -E ab\\\\cd file         ab\\cd         ab\cd    * 
grep -E ab\\\\\cd file        ab\\\cd        ab\cd    *
grep -E ab\\\\\\cd file       ab\\\cd        ab\cd    *    
grep -E ab\\\\\\\cd file      ab\\\cd        ab\cd    *
grep -E ab\\\\\\\\cd file     ab\\\\cd       ab\\cd

grep -E "ab\cd" file          ab\cd          abcd
grep -E "ab\\cd" file         ab\cd          abcd
grep -E "ab\\\cd" file        ab\\cd         ab\cd    *
grep -E "ab\\\\cd" file       ab\\cd         ab\cd    *
grep -E "ab\\\\\cd" file      ab\\\cd        ab\cd    *
grep -E "ab\\\\\\cd" file     ab\\\cd        ab\cd    *
grep -E "ab\\\\\\\cd" file    ab\\\\cd       ab\\cd    

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