"then"과 "there"가 포함된 파일이 있습니다.
저 할 수 있어요
$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some
저 할 수 있어요
$ grep "there " x.x
If there is no blob none some will be created
한 번의 작업으로 두 가지를 모두 검색하는 방법은 무엇입니까? 나는 노력했다
$ grep (then|there) x.x
-bash: 예상치 못한 표시 "(" 근처에서 구문 오류가 발생했습니다.
그리고
grep "(then|there)" x.x
durrantm.../code
# (Nothing)
답변1
표현식을 따옴표로 묶어야 합니다. 귀하가 겪고 있는 오류는 bash가 (
특수 문자로 해석한 결과입니다 .
또한 확장 정규식을 사용하려면 grep에 지시해야 합니다.
$ grep -E '(then|there)' x.x
|
확장 정규 표현식이 없으면 , (
및 를 이스케이프해야 합니다 )
. 여기서는 작은따옴표를 사용하고 있습니다. Bash는 큰따옴표 안의 백슬래시를 특별히 처리합니다.
$ grep '\(then\|there\)' x.x
이 경우 그룹화는 필요하지 않습니다.
$ grep 'then\|there' x.x
다음과 같은 경우에 필요합니다.
$ grep 'the\(n\|re\)' x.x
답변2
참고로 대부분의 버전에는 -E를 사용한 grep인 egrep이라는 명령이 있습니다. 나는 개인적으로 타이핑을 더 좋아한다.
egrep "i(Pod|Pad|Phone)" access.log
grep -E를 사용하는 것보다
답변3
(또는 적어도 내 것은) 매뉴얼 페이지의 정규식 아래에 문서화되어 있는 내용은 실제로확장하다정규식;
grep은 "기본", "확장" 및 "perl"이라는 세 가지 버전의 정규식 구문을 이해합니다. GNU grep에서는 기본 구문과 확장 구문 간에 사용 가능한 기능에 차이가 없습니다. 다른 구현에서는 기본 정규 표현식이 덜 강력합니다. 다음 설명은 확장 정규식에 적용됩니다.그 다음에는 기본적인 정규식 차이점에 대한 요약이 이어집니다.
그러나 grep은 기본적으로 이를 사용하지 않습니다. 스위치가 필요합니다 -E
.
grep "(then|there)" x.x
왜냐하면 (맨 페이지에서 다시):
기본 정규식과 확장 정규식
기본 정규식에서는 메타 문자 ?, +, {, |, ( 및 )가 특별한 의미를 잃습니다. 대신 백슬래시 버전 \?, +, {, \|, ( 및 )가 사용됩니다.
따라서 다음을 사용할 수도 있습니다.
grep "then\|there" x.x
이 경우 대괄호가 중복되기 때문입니다.
답변4
Bash의 우아한 단순성은 방대한 매뉴얼 페이지에서 사라진 것 같습니다.
위의 훌륭한 솔루션 외에도 치트 시트를 제공하려고 생각했습니다.Bash가 명령문을 구문 분석하고 해석하는 방법. 그런 다음 이 로드맵을 사용하여 질문자가 제공한 예제를 구문 분석하여 예상대로 작동하지 않는 이유를 더 잘 이해할 수 있도록 도와드리겠습니다.
참고: Shell 스크립트 줄을 직접 사용하십시오. 입력된 입력 행은 먼저 역사적으로 확장됩니다.
각 bash 라인은 먼저 토큰화됩니다., 즉, 소위 말하는 것으로 잘라냅니다.토큰. (토큰화는 중괄호, 물결표, 매개변수, 명령, 산술, 프로세스, 토큰화 및 파일 이름 확장을 포함한 다른 모든 확장 전에 발생합니다.)
여기서 토큰은 다음 특수 메타 문자 중 하나로 구분된(구분된) 입력 줄의 일부를 나타냅니다.
space, - White space...
tab,
newline,
‘<’, - Redirection & piping...
‘|’,
‘>’
‘&’, - And/Both < | > | >> .or. &<file descriptor>
‘;’, - Command termination
‘(’, - Subshell, closed by - ‘)’
Bash는 다른 많은 특수 문자를 사용하지만 이 10개만 초기 토큰을 생성합니다.
그러나 이러한 메타 문자는 때때로 토큰에서도 사용되어야 하므로 특별한 의미를 제거하는 방법이 필요합니다. 이것을 탈출이라고 합니다. 이스케이프는 하나 이상의 문자로 구성된 문자열(예: 'xx..'
, "xx.."
)을 인용하거나 단일 문자 앞에 백슬래시를 추가하여 수행할 수 있습니다(예: \x
). (따옴표도 인용해야 하고 큰따옴표가 모든 것을 인용하지는 않기 때문에 그보다 조금 더 복잡하지만 지금은 이렇게 단순화하면 됩니다.)
bash 인용을 다른 언어에서와 마찬가지로 텍스트 문자열을 인용하는 아이디어와 혼동하지 마십시오. Bash에서 따옴표 사이에 있는 것은 문자열이 아니라 입력 줄의 메타문자 이스케이프 부분이므로 토큰을 분리하지 않습니다.
'
, 및 사이에는 중요한 차이가 있지만 "
이는 나중에 다루겠습니다.
이스케이프 처리되지 않은 나머지 메타 문자는 토큰 구분 기호가 됩니다.
예를 들어,
$ echo "x"'y'\g
xyg
$ echo "<"'|'\>
<|>
$ echo x\; echo y
x; echo y
echo
첫 번째 예에는 공백 구분 기호로 생성된 두 개의 토큰( 및 )이 있습니다 xyz
.
두 번째 예도 마찬가지다.
세 번째 예에서는 세미콜론이 이스케이프되므로 공백 구분 기호 , , 및 echo
4개의 x;
토큰이 echo
생성 됩니다 y
. 그러면 첫 번째 토큰이 명령으로 실행되고 다음 세 토큰을 입력으로 받아들입니다. 두 번째 것은 echo
실행되지 않습니다.
기억해야 할 중요한 점은 bash가 먼저 이스케이프 문자( '
, "
및 \
)를 찾은 다음 이스케이프되지 않은 메타 문자 구분 기호를 순서대로 찾는다는 것입니다.
이스케이프하지 않으면 이러한 10개의 특수 문자가 token
구분 기호로 사용됩니다. 그 중 일부는 다른 의미도 있지만 무엇보다도 토큰 구분 기호입니다.
grep이 기대하는 것
위의 예에서 grep에는 , , grep
태그 가 필요합니다 .string
filename
이 문제에 대한 첫 번째 시도는 다음과 같습니다.
$ grep (다음 | 거기) xx
이 예에서 (
, )
, 및 는 이스케이프 되지 않은 메타 문자이므로 입력을 , , , , 및 |
토큰으로 분할하는 데 사용됩니다 . grep은 , 및 을 (를) 보고 싶어합니다 .grep
(
then
|
there
)
x.x
grep
then|there
x.x
문제에 대한 두 번째 시도는 다음과 같습니다.
grep "(그때|거기)"xx
grep
, (then|there)
, 로 표시되어 있습니다 x.x
. grep을 echo로 바꾸면 다음을 볼 수 있습니다.
echo "(그때|거기)" xx
(그때|거기) xx