sed를 사용하여 각 줄의 시작 부분에서 다양한 길이의 숫자 캡처

sed를 사용하여 각 줄의 시작 부분에서 다양한 길이의 숫자 캡처

다음 형식의 파일을 작업 중입니다.

12345:ABCDEFG

789:HIJK

4963158:LMNOPQRSTUV

각 줄은 다양한 길이로 시작하고 그 뒤에 콜론, 다양한 길이의 문자열이 옵니다. 아래와 같이 각 줄의 시작 부분에 있는 숫자만 캡처하여 새 파일에 넣고 싶습니다.

12345

789

4963158

이것은 내가 얻은 것과 가장 가깝지만 숫자뿐만 아니라 전체 줄을 인쇄합니다.

sed -r 's/([^0-9]+d)(:)([A-Z]+)$/\1/' example.txt >> justnumbers.txt

내가 문법적으로 뭘 잘못하고 있는 걸까?

답변1

때로는 문제를 다른 방식으로 바라보면 더 간단한 답을 얻을 수 있습니다.

"이전의 모든 숫자를 유지하고 싶습니다."라고 생각하는 것은 매우 합리적입니다. 또 다른 관점으로는 “처음부터 끝까지 모든 것을 버리고 싶다”라고 볼 수도 있다.

이로 인해

s/:.*//

sed 명령으로.

예를 들어

$ cat x
12345:ABCDEFG
789:HIJK
4963158:LMNOPQRSTUV

$ sed 's/:.*//' x
12345
789
4963158

답변2

요점이 :각 줄의 첫 번째 줄의 남은 부분을 반환하는 것이라면 다음을 수행하십시오.

<your-file cut -d: -f1

-s옵션을 추가하면 모든 :.

:하나 이상의 ASCII 숫자와 하나 이상의 ASCII 대문자로 구성된 줄의 나머지 부분을 반환하고 :패턴과 일치하지 않는 줄을 삭제하려면 sed//를 사용할 수 있습니다 awk.perl

<your-file sed -n '^\([0123456789]\{1,\}\):[ABCDEFGHIJKLMNOPQRSTUVWXYZ]\{1,\}$/\1/p'

또는:

<your-file LC_ALL=C sed -n 's/^\([0-9]\{1,\}\):[A-Z]\{1,\}$/\1/p'

( 로케일은 이러한 범위가 첫 번째 명령에서 명시적으로 설정된 것과 동일함을 C보장하는 유일한 것입니다 .)[0-9][A-Z]

또는 sed정규식 확장 -E옵션을 지원하는 경우 E(60년대가 아닌 70년대부터 확장되었지만 sed구현에서는 90년대 후반까지 이에 대한 지원을 추가하기 시작하지 않았습니다):

<your-file LC_ALL=C sed -nE 's/^([0-9]+):[A-Z]+$/\1/p'

또는 다음을 사용하십시오 perl(80년대 정규식 사용).

<your-file perl -lne 'print $1 if /^(\d+):[A-Z]+$/'

pcregrep유사한 정규식을 grep사용 하고 첫 번째 캡처 그룹 출력을 지원하는 구현 입니다 .perl-o<n>n

<your-file pcregrep -xo1 '(\d+):[A-Z]+'

일부 grep구현에는 -o옵션이 있지만 전체 일치 항목만 출력하지만 일부 구현에서는 -P유사 연산자를 사용하여 일치 항목을 포함하지 않고 내용을 검사할 수 있는 Perl과 같은 정규식 사용을 지원합니다.

<your-file grep -Po '^(\d+)(?=:[A-Z]+$)'

(?=...), :1개 이상의 [A-Z]s(perl 정규 표현식에서는 로케일을 구분하지 않으므로 LC_ALL=C필요하지 않음), 그리고 줄 끝이 뒤따르는 경우 줄 시작 부분에 있는 1개 이상의 숫자 시퀀스와 일치합니다 .


공평하게 말하자면, 그 이후로 그들은 모두 진화해 왔으며 특히 Perl이 그러했습니다. 1970년대 후반 ERE는 +, ?|(더 중요한 것은 일치를 위한 새로운 알고리즘)을 추가했지만 \x역참조가 손실되었습니다. \{min,max\}은 80년대 후반에 BRE에 추가되었고( +및 과 동일한 작업을 수행할 수 있음 ?) {min,max}나중에 ERE에 다시 추가되었지만 이전 버전과의 호환성이 손상되었기 때문에 항상 그런 것은 아닙니다. POSIX는 일부 [[:class:]], [[=x=]], [[.x.]](더 좋거나 더 가치 있기 위해)를 도입합니다. BRE/ERE의 일부 구현 에는 perl또는 .\d*?

답변3

이 시도:

sed -E 's/([0-9]+):[A-Z]+/\1/' example.txt

-E동일 -r하지만 이제 좀 더 표준이 되었습니다.

정규식의 문제는 표현식 시작 부분( [^0-9])에 음수 대괄호를 사용한 다음 리터럴 d문자를 일치시킨다는 것입니다.

또한 필요하지 않은 추가 캡처 그룹도 제거했습니다.

전반적으로 엄청난 노력을 기울였습니다! 너희들은 정말 가깝다. 정규식을 사용하기 시작할 때 직면하게 되는 질문은 다음과 같습니다.

답변4

사용행복하다(이전 Perl_6)

~$ raku -pe 's/^ (\d+) \: .* $/$0/;'  file

#OR

~$ raku -pe 's/^ \d+ <( \: .* $//;'  file

다양한 정규식 구현을 살펴보면 공통 주제를 찾는 데 도움이 될 수 있습니다. Perl 및 Raku의 경우 -pe명령줄 플래그는 sed유사한 동작을 제공하여 각 줄에서 코드를 실행하고 자동으로 인쇄합니다.

위의 첫 번째 Raku 예는 ^문자열의 시작 부분 \d+(하나 이상의 숫자), :콜론(백슬래시 이스케이프 처리됨) 및 문자열 끝까지(즉, 줄) .*0번 이상의 문자를 캡처합니다. $Raku 캡처는 일치하는 개체의 절반(즉, 전체 행)을 대체하는 데 사용되는 $0캡처된 숫자 로 시작됩니다.$0s///

위의 두 번째 Raku 예는 반대 접근 방식을 취합니다. ^문자열의 시작 부분 \d+(1개 이상)과 일치하고 그 뒤에는 :콜론(백슬래시로 이스케이프 처리됨) 및 .*문자열 $끝까지(예: 줄 ) . 그러나 <("캡처 태그"는 Raku의 정규식 엔진에 \d+일치하는 개체에서 앞의 숫자를 제거하고 뒤의 숫자만 남겨두도록 지시합니다. 대체에서는 일치하는 객체에 남아 있는 모든 항목이 제거되므로(다른 항목으로 대체) \d+문자열 시작 부분의 숫자만 남습니다.

https://docs.raku.org/언어/regexes#Capture_markers:_%3C(_)%3E
https://docs.raku.org/언어/regexes
https://raku.org

관련 정보