이 경우 grep이 제대로 작동하지 않는 이유는 무엇입니까?

이 경우 grep이 제대로 작동하지 않는 이유는 무엇입니까?

다음 내용이 포함된 file2.txt 파일을 고려해 보세요.

P 89 24 -1.5388040474568784e+01 7.4421775186012660e+00 -1.3143195543234219e+03 1.3168884860257754e+03 8.0419002445999993e+01 44 0 0 -97 0
P 122 -4 -1.4869334602986523e+01 5.7316939411954255e+00 -1.3144161801429666e+03 1.3169704096915282e+03 8.0419002445999993e+01 44 0 0 -370 0
P 493 -24 -1.4690576431881317e+01 7.3848907323212831e+00 -1.3144620647251766e+03 1.3170224315489374e+03 8.0419002445999993e+01 62 0 0 -499 0
E 3 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 9999 0 970 1 2 0 7 1.7003962000000002e+05 8.5019810000000018e-01 8.5019810000000018e-01 8.5019810000000018e-01 3.0000000000000000e+01 3.8153441026312507e+01 1.0000000000000000e+11
E 4 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 9999 0 818 1 2 0 7 1.7003962000000002e+05 8.5019810000000018e-01 8.5019810000000018e-01 8.5019810000000018e-01 3.0000000000000000e+01 3.2509364886711985e+01 1.0000000000000000e+11
P 5 2 0 0 3.7531787088999999e+02 3.8383684055052936e+02 8.0419002445999993e+01 22 0 0 -6 0
P 8 24 7.0195398693654170e+00 3.1543502387874696e+01 5.5989200759599044e+01 1.0318077843755555e+02 8.0419002445999993e+01 44 0 0 -50 0
P 67 28 5.8271676589304882e+00 3.3476871962084061e+01 5.6723118833601163e+01 1.0411236719963519e+02 8.0419002445999993e+01 44 0 0 -168 0
P 219 13 6.0328453988772415e+00 3.3531592253635168e+01 5.6777179460595200e+01 1.0417114266715717e+02 8.0419002445999993e+01 44 0 0 -329 0
P 444 -24 6.4646967953734418e+00 3.4909545978243479e+01 5.7879920796889749e+01 1.0525098522544691e+02 8.0419002445999993e+01 62 0 0 -452 0
E 5 -1 -1.0000000000000000e+00 -1.0000000000000000e+00 -1.0000000000000000e+00 9999 0 598 1 2 0 7 1.7003962000000002e+05 0 0 8.5019810000000018e-01 3.0000000000000000e+01 6.8997318544430456e+01 1.0000000000000000e+11

나는 단지 문자열 P ... 24 ...또는 을 추출하고 싶습니다 P ... -24 .... 이것이 제가 한 일입니다:

cat file2.txt | grep -E '(P [0-9]+ 24 | P [0-9] + -24 |P [0-9][0-9]+ 24 | P [0-9][0-9] + -24 |P [0-9][0-9][0-9] + 24 | P [0-9][0-9][0-9] + -24 |P [0-9][0-9][0-9][0-9]+ 24 | P [0-9][0-9][0-9][0-9] + -24 )' &> file3.txt

그러나 생성된 file3.txt에는 문자열만 포함되어 있습니다 P ... 24. 내가 뭘 잘못하고 있는지 말해 줄 수 있나요?

답변1

.... 내가 뭘 잘못했나요? ...더 복잡하게 만드는 것 외에도... 모든 경우 -24와 다른 경우에 문자열에 없는 여러 공백과 선행 공백을 일치시키려고 합니다 ...

P [0-9]+ 24 |

알겠습니다 P. 일련의 숫자 [0-9]+공백 24을 차례로 입력하세요.

| P [0-9] + -24 |

여기의 숫자 앞과 뒤에는 하나 이상의 공백이 있고, 그 뒤에는 추가 공백으로 인해 일치할 수 없는 또 다른 공백이 옵니다.P+

|P [0-9][0-9]+ 24 |

다시 한 번 잘 작동하지만 모든 일치 항목이 이미 첫 번째 패턴에서 캡처되었으므로 중복됩니다.

| P [0-9][0-9] + -24 |

추가 공백, 위와 동일 -24... 일치하지 않음

|P [0-9][0-9][0-9] + 24 |

예전에 여유공간이 있었 어서 다시 2개 이상 +찾아보게 되더라구요 ...

| P [0-9][0-9][0-9] + -24 |

the 앞에는 선행 공백이 있고, 다시 P2개 이상의 공백이 앞에 옵니다.-24

|P [0-9][0-9][0-9][0-9]+ 24 |

훌륭하지만 중복됨

| P [0-9][0-9][0-9][0-9] + -24

the 앞에는 선행 공백이 있고, 다시 P2개 이상의 공백이 앞에 옵니다.-24

@gillesquenot은 더 우아한 솔루션을 제공하지만 추가 공간을 잃어도 솔루션이 "작동"합니다...

grep -E '(P [0-9]+ 24 |P [0-9]+ -24 |P [0-9][0-9]+ 24 |P [0-9][0-9]+ -24 |P [0-9][0-9][0-9] + 24 |P [0-9][0-9][0-9]+ -24 |P [0-9][0-9][0-9][0-9]+ 24 |P [0-9][0-9][0-9][0-9]+ -24 )'

여러 공간을 사용할 수 있는 경우

grep -E '^P +[0-9]+ +-?24'

편집하다

이것문자열에서 일치하는 내용과 위치를 확인하는 데 유용한 리소스입니다.

답변2

미션 같은데! 이것은DSL1: 이것이 바로 awk가는 길입니다.
간단하고 재사용이 가능하며 효율적이고 빠릅니다.

아니요정규식:

awk '$1 == "P" && ($3 == "-24" || $3 == "24")' file2.txt 

또는 사용정규식:

awk '$1 == "P" && $3 ~ /^-?24$/' file2.txt 

여기서 정규 표현식에서 /^-?24$/대시는 선택 사항이므로 이 짧은 문자를 사용할 수 있습니다.정규식.


정규식 일치는 다음과 같습니다.
마디 설명하다
^ 문자열의 시작
-? '-'(선택 사항(최대한 많이 일치))
24 '스물넷'
$ 선택적 \n 앞과 문자열 끝

1 가장 유명한 채팅에 질문을 해보세요

Q: DSL은 개발자에게 무엇을 의미합니까?

DSL(도메인 특정 언어)는 특정 작업을 보다 쉽게 ​​코딩할 수 있도록 설계된 컴퓨터 언어입니다. 특정 애플리케이션 도메인에 맞게 조정되어 개발자가 빠르고 효율적으로 코드를 작성할 수 있습니다. DSL의 일반적인 용도에는 데이터베이스 쿼리, 텍스트 처리 및 과학 시뮬레이션이 포함됩니다. DSL을 사용하면 개발자는 특정 목적을 위한 애플리케이션을 신속하게 구축하여 보다 직관적인 프로그래밍 접근 방식을 제공하고 구문에 대한 의존도를 줄일 수 있습니다.

답변3

정규식을 조금 단순화해 보겠습니다.

grep -E '^P [0-9]+ -?24\b' file2.txt 

원하지 않는 복잡성과 가독성 외에도 정규식의 주요 문제점은 잘못된 공백을 추가로 사용한다는 것입니다.

불필요한:

입력에 더 많은 공간을 확보할 수 있다고 생각되면 다음 중 하나를 사용할 수 있습니다.

  • +
  • [[:space:]]+( POSIX문자 클래스)
  • \s+-P일명 PCRE스위치가 필요하다grep

정규식 일치는 다음과 같습니다.

마디 설명하다
^ 선 기준점의 시작점
P 'P'+스페이스
[0-9]+ 모든 문자: "0" ~ "9"(1회 이상(최대한 많이 일치))
공간
-? '-'(선택 사항(최대한 많이 일치))
24 '스물넷'
\b 단어 경계

답변4

글쎄, 값이 24일 수 있는 하나의 필드에만 의존하고 있는 것입니다. 이는 잘못된 설계처럼 보입니다. 예를 들어 cut추가 분석을 위해 해당 파일에서 첫 번째 및 세 번째 열을 추출할 수 있는 도구가 많이 있습니다 .

하지만 솔직하게 말하자면 이는 sed또는 와 같은 cut문자열 엔진 이 아니라 표 형식의 숫자 데이터를 처리하는 도구의 작업입니다 grep.

솔직히 말해서, 몇 줄의 Python(또는 Perl 또는... 원하는 프로그래밍 언어)이 이 문제를 해결할 것입니다. 어쨌든 여기서 결과를 프로그래밍 방식으로 처리할 것이라고 100% 확신합니다. 시작 언어부터.

간단히 설명하면 다음과 같습니다.

#!/usr/bin/env python3
import sys

with open(sys.argv[1], "r", encoding="ascii") as inputfile:
  linecounter = 0
  for line in inputfile:
    linecounter += 1
    try:
      if not line.startswith("P "):
         continue # skip this line alltogether
      thirdpos = int(line.split(" ")[2])
      if not (thirdpos == 24 or thirdpos == -24):
         continue
      print(line) # or actually, do something useful with the line
    except Exception as e:
      print("Exception occurred on line {linecounter}, '{line}':\n{e}", sys.stderr)

텍스트 파일에서 chmod 755 thatfile, 를 실행한 다음 /path/to/thatfile /path/to/input_file.

관련 정보