다음 형식의 파일을 작업 중입니다.
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
캡처된 숫자 로 시작됩니다.$0
s///
위의 두 번째 Raku 예는 반대 접근 방식을 취합니다. ^
문자열의 시작 부분 \d+
(1개 이상)과 일치하고 그 뒤에는 :
콜론(백슬래시로 이스케이프 처리됨) 및 .*
문자열 $
끝까지(예: 줄 ) . 그러나 <(
"캡처 태그"는 Raku의 정규식 엔진에 \d+
일치하는 개체에서 앞의 숫자를 제거하고 뒤의 숫자만 남겨두도록 지시합니다. 대체에서는 일치하는 객체에 남아 있는 모든 항목이 제거되므로(다른 항목으로 대체) \d+
문자열 시작 부분의 숫자만 남습니다.
https://docs.raku.org/언어/regexes#Capture_markers:_%3C(_)%3E
https://docs.raku.org/언어/regexes
https://raku.org