답변:
이것을 작동시키는 열쇠는 sed
출력하고 싶지 않은 것을 제외하고 원하는 것을 지정하는 것입니다.
string='This is a sample 123 text and some 987 numbers'
echo "$string" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
이것은 말합니다 :
-n
)p
)일반적으로 sed
괄호를 사용하여 그룹을 캡처하고 역 참조를 사용하여 캡처 한 내용을 출력합니다.
echo "foobarbaz" | sed 's/^foo\(.*\)baz$/\1/'
"bar"를 출력합니다. 확장 정규식에 -r
( -E
OS X의 경우)를 사용하는 경우 괄호를 이스케이프 처리하지 않아도됩니다.
echo "foobarbaz" | sed -r 's/^foo(.*)baz$/\1/'
최대 9 개의 캡처 그룹과 역 참조가있을 수 있습니다. 역 참조는 그룹이 나타나는 순서대로 번호가 매겨 지지만 어떤 순서로든 사용할 수 있으며 반복 될 수 있습니다.
echo "foobarbaz" | sed -r 's/^foo(.*)b(.)z$/\2 \1 \2/'
"바 a"를 출력합니다.
GNU가있는 경우 grep
(OS X를 포함하여 BSD에서도 작동 할 수 있음) :
echo "$string" | grep -Po '\d+'
또는 다음과 같은 변형 :
echo "$string" | grep -Po '(?<=\D )(\d+)'
이 -P
옵션은 Perl 호환 정규 표현식을 활성화합니다. man 3 pcrepattern
또는을 참조하십시오 man
3 pcresyntax
.
sed
예제를 참조하는 경우 -r
옵션 (또는 -E
OS X, IIRC)을 사용하는 경우 괄호를 이스케이프 할 필요가 없습니다. 차이점은 기본 정규 표현식과 확장 정규 표현식 ( -r
) 의 차이점입니다 .
sed -e 's/version=\(.+\)/\1/' input.txt
이것은 여전히 전체 input.txt를 출력합니다
\+
대신 작성해야합니다 +
. 그리고 사람들이 왜 -e
단 하나의 sed 명령을 사용하는지 이해하지 못합니다 .
sed -e -n 's/version=\(.+\)/\1/p' input.txt
참조하십시오 : mikeplate.com/2012/05/09/…
sed -E
Perl / Java / JavaScript / Go / whatever에 가장 가까운 소위 "현대"또는 "확장 된"정규 표현식을 사용하는 것이 좋습니다 . (에 비교 grep -E
나 egrep
.) 기본 구문은 그 이상한 탈출 규칙을 가지고 있으며, "쓸모없는"것으로 간주됩니다. 이 둘의 차이점에 대한 자세한 내용을 보려면을 실행하십시오 man 7 re_format
.
당신은 grep을 사용할 수 있습니다
grep -Eow "[0-9]+" file
o
옵션이있는 이유 -unixhelp.ed.ac.uk/CGI/man-cgi?grep : -o, --only-matching 일치하는 행의 일부만 패턴
grep -Eow -e "[0-9]+" -e "[abc]{2,3}"
이 두 표현식이 이전 grep에서 파이핑을 제외하고 한 줄에 있어야하는 방법을 모르겠습니다 (한 패턴이 한 줄에서 두 번 이상 일치하면 여전히 작동하지 않습니다) ).
이 답변은 모든 숫자 그룹에서 작동합니다. 예:
$ echo 'Num123that456are7899900contained0018166intext' |
> sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
sed에게 캡처 된 그룹 만 출력하도록 지시 할 수있는 방법이 있습니까?
예. 캡처 그룹으로 모든 텍스트를 대체하십시오.
$ echo 'Number 123 inside text' | sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*/\1/'
123
s/[^0-9]* # several non-digits
\([0-9]\{1,\}\) # followed by one or more digits
[^0-9]* # and followed by more non-digits.
/\1/ # gets replaced only by the digits.
또는 확장 된 구문 (역 따옴표가 적고 + 사용 가능) :
$ echo 'Number 123 in text' | sed -E 's/[^0-9]*([0-9]+)[^0-9]*/\1/'
123
숫자가 없을 때 원본 텍스트를 인쇄하지 않으려면 다음을 사용하십시오.
$ echo 'Number xxx in text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1/p'
그리고 여러 숫자를 일치시키고 인쇄하십시오.
$ echo 'N 123 in 456 text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456
그것은 모든 자릿수 실행에 효과적입니다.
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/\1 /gp'
123 456 7899900 0018166
grep 명령과 매우 유사합니다.
$ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
$ echo "$str" | grep -Po '\d+'
123
456
7899900
0018166
그리고 패턴 :
/([\d]+)/
Sed는 '\ d'(바로 가기) 구문을 인식하지 못합니다. 위에서 사용 된 ascii 등가 [0-9]
는 정확히 동일하지 않습니다. 유일한 대안은 '[[: digit :]]`문자 클래스를 사용하는 것입니다.
선택한 답변은 이러한 "문자 클래스"를 사용하여 솔루션을 빌드합니다.
$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
이 솔루션은 (정확히) 두 자리 숫자 만 작동합니다.
물론, 셸 내에서 답변이 실행됨에 따라 이러한 답변을 더 짧게하기 위해 몇 가지 변수를 정의 할 수 있습니다.
$ str='This is a sample 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/\1 \2/p"
그러나 이미 설명했듯이 s/…/…/gp
명령을 사용하는 것이 좋습니다.
$ str='This is 75577 a sam33ple 123 text and some 987 numbers'
$ d=[[:digit:]] D=[^[:digit:]]
$ echo "$str" | sed -rn "s/$D*($d+)$D*/\1 /gp"
75577 33 123 987
그것은 반복되는 자릿수와 짧은 명령을 쓰는 것을 다룰 것입니다.
질문에 주어진 패턴은 단지 예일 뿐이며 목표는 모든 패턴 과 일치 하는 것이라고 생각합니다 .
패턴 공간에 줄 바꿈을 삽입 할 수있는 GNU 확장 이있는 sed 가있는 경우 한 가지 제안은 다음과 같습니다.
> set string = "This is a sample 123 text and some 987 numbers"
>
> set pattern = "[0-9][0-9]*"
> echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
123
987
> set pattern = "[a-z][a-z]*"
> echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
his
is
a
sample
text
and
some
numbers
이 예제는 CYGWIN 과 함께 tcsh (예, 잘못된 쉘을 알고 있습니다 )와 함께 있습니다. (편집 : bash의 경우 세트를 제거하고 = 주위의 공백을 제거하십시오.)
+
이스케이프를 이스케이프 처리하거나 -r
옵션 ( -E
OS X의 경우)을 사용해야합니다 . 당신은 또한 사용할 수 있습니다 \{1,\}
(또는 -r
또는 -E
이스케이프없이).
포기하고 펄을 사용하십시오
때문에 sed
그것을 잘라하지 않는, 그냥 그것이 적어도 펄 수건을 던져 사용할 수 있도록 LSB 동안 grep
GNU 확장이되지 않습니다 :-)
일치하는 그룹이나 룩업이 필요없는 전체 일치 부분을 인쇄하십시오.
cat <<EOS | perl -lane 'print m/\d+/g'
a1 b2
a34 b56
EOS
산출:
12
3456
라인 당 단일 일치, 종종 구조화 된 데이터 필드 :
cat <<EOS | perl -lape 's/.*?a(\d+).*/$1/g'
a1 b2
a34 b56
EOS
산출:
1
34
lookbehind와 함께 :
cat <<EOS | perl -lane 'print m/(?<=a)(\d+)/'
a1 b2
a34 b56
EOS
여러 필드 :
cat <<EOS | perl -lape 's/.*?a(\d+).*?b(\d+).*/$1 $2/g'
a1 c0 b2 c0
a34 c0 b56 c0
EOS
산출:
1 2
34 56
라인 당 여러 개의 일치, 종종 구조화되지 않은 데이터 :
cat <<EOS | perl -lape 's/.*?a(\d+)|.*/$1 /g'
a1 b2
a34 b56 a78 b90
EOS
산출:
1
34 78
lookbehind와 함께 :
cat EOS<< | perl -lane 'print m/(?<=a)(\d+)/g'
a1 b2
a34 b56 a78 b90
EOS
산출:
1
3478
시험
sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/\1 \2 \3 \4 \5 \6 \7 \8 \9/p"
cygwin에서 이것을 얻었습니다.
$ (echo "asdf"; \
echo "1234"; \
echo "asdf1234adsf1234asdf"; \
echo "1m2m3m4m5m6m7m8m9m0m1m2m3m4m5m6m7m8m9") | \
sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/\1 \2 \3 \4 \5 \6 \7 \8 \9/p"
1234
1234 1234
1 2 3 4 5 6 7 8 9
$
sed
사용하여 확장 정규식을 설정 해야 합니다-E
.