Linux 환경에서 문자열을 조작하기 위한 많은 패키지(grep, awk, sed...)가 있다는 점을 고려하면 php/preg와 유사한 구문으로 캡처 그룹을 추출하는 소프트웨어가 필요합니다.
어쩌면 가장 가까운 것일 수도 있지만 grep -P
그것이 어떻게 작동하는지 이해하지 못합니다.
이와 같은 것은 cat file.txt | grep -P '/something="([\w]+)"/i'
캡처 그룹 내부에 있는 것 이상의 것을 제공하는 것 같습니다.
누군가 나에게 몇 가지 실제 사례를 제공할 수 있습니까? 저를 지원하고 몇 가지 변형과 제한 사항을 설명해 주세요!
편집: 어딘가에서 이를 달성하는 데 사용되는 것을 보았지만 sed
여전히 구문에 대해 약간 혼란스럽습니다.
답변1
pcregrep -io1 'something="(\w+)"' myfile.txt
( -i
대소문자를 구분하지 않는 일치의 경우 -o1
첫 번째 캡처링 그룹이 인쇄됩니다.)
GNU grep
지원 -P
(perl 호환 정규식 지원으로 구축된 경우) 및 -o
. -o
그러나 Perl 둘러보기 연산자를 사용하여 이 문제를 해결할 수 있습니다.
grep -iPo '(?<=something=")\w+(?=")' myfile.txt
(즉, 시퀀스와 일치하는 정규식문자를 형성하는 단어단, 뒤에 ) something="
가 따라야 합니다 "
.
또는 가장 가까운 PCRE를 사용하십시오.
grep -iPo 'something="\K\w+(?=")' myfile.txt
( \K
재설정일치끈).
그러나 Perl 정규 표현식을 사용하려면 다음을 사용할 수도 있습니다 perl
.
perl -C -lne 'print for /something="(\w+)"/ig' myfile.txt
GNU 또는 BSD를 사용하면 sed
각 줄의 가장 오른쪽 일치 항목만 반환됩니다.
sed -nE 's/.*something="(\w+)".*/\1/pi' myfile.txt
이식 가능(확장 정규식 지원 및 대소문자를 구분하지 않는 일치는 비표준 확장이며 sed
모든 구현에서 지원되지 않기 때문):
sed -n 's/.*[sS][oO][mM][eE][tT][hH][iI][nN][gG]="\([[:alnum:]_]\{1,\}\)".*/\1/p' myfile.txt
대문자가 i
이라고 가정합니다 I
. 이는 예를 들어 대문자가 있는 로케일에서는 동작이 이전 솔루션과 다르다는 것을 의미 i
합니다 İ
.
연속적으로 모든 항목을 찾는 표준/휴대용 솔루션:
awk '{while(match(tolower($0), /something="[[:alnum:]_]+"/)) {
print substr($0, RSTART+11, RLENGTH-12)
$0 = substr($0, RSTART+RLENGTH-1)}}' myfile.txt
입력에 길이(문자 수)가 다른 소문자 버전의 텍스트가 포함된 경우 올바르게 작동하지 않을 수 있습니다.
덫:
\w
[[:alnum:]_]
C/POSIX 이외의 로케일에서의 일치 와 관련하여 이러한 모든 솔루션 간에는 약간의 차이가 있습니다. 어떤 경우든 최소한 밑줄, 모든 10진수 아라비아 숫자, 라틴 영어 알파벳(대문자 및 소문자)이 포함되어야 합니다. 이것이 필요한 전부라면 로케일을 C로 수정하세요.- 위에서 언급했듯이 대소문자를 구분하지 않는 일치는 로케일에 따라 크게 달라집니다.
a-z
대 영어 문자 에만 관심이 있다면A-Z
로케일을 C로 다시 수정할 수 있습니다. .
적어도 GNU 구현에서 정규식 연산자는sed
유효한 문자가 아닌 바이트 시퀀스와 일치하지 않습니다. 예를 들어, UTF-8 로케일에서 이는 비트 8이 설정된 단일 바이트 문자 세트의 문자와 일치하지 않음을 의미합니다. 즉,sed
솔루션이 올바르게 작동하려면 입력 파일에 사용된 문자 집합이 사용자 로케일의 문자 집합과 동일해야 합니다.perl
,pcregrep
GNU 유틸리티는 일반적으로 임의의 길이와 임의의 바이트 값을 포함하는 행을 처리하며(그러나 위의 경고에 유의) 마지막 개행 문자 뒤의 추가 데이터를 추가 행으로 처리합니다. 이러한 유틸리티의 다른 구현은 그렇지 않을 수도 있습니다.위 패턴은 입력의 각 줄을 차례로 일치시킵니다. 이는 둘 이상의 입력 행과 일치할 수 없음을 의미합니다. 두 줄 이상에 걸쳐 있을 수 없는 이와 같은 패턴에서는 문제가 되지 않지만
something="\w+"
, 일반적인 경우 패턴이 여러 줄에 걸쳐 있을 수 있는 텍스트와 일치하도록 하려면something=".*?"
다음이 필요합니다.- 처리하는 레코드 유형을 변경합니다.
grep --null
,sed -z
(sed
GNU 전용),perl -0
,awk -v RS='\0'
( GNUawk
및 최신 버전 전용mawk
) 줄 대신 NUL 구분 레코드를 처리할 수 있습니다(개행 구분 레코드). GNU는awk
정규 표현식을 레코드 구분 기호로 사용할 수 있습니다(-v RS='regexp'),
perlany byte value (with
-0ooo` 사용). pcregrep
여러 줄 모드 가 있습니다-M
.perl
전체 입력이 레코드인 후루룩 모드 사용 ( 사용-0777
)
그런 다음 perl 및 pcre의 경우
.
플래그가 활성화되어 있지 않으면 개행이 일치하지 않습니다s
. 예를 들어pcregrep -Mio1 '(?s)something="(.*?)"'
또는perl -C -l -0777 -ne 'print for /something="(.*?)"/gis'
- 처리하는 레코드 유형을 변경합니다.
grep
및 의 일부 버전에는 또는 버그가pcregrep
있으며 정규식 엔진에는 일반적으로 정규식 일치에 투입할 수 있는 작업량에 대한 기본 제한이 있습니다.-z
-M
답변2
Linux에는 각각 다른 기능을 가진 여러 명령이 있습니다. - 귀하의 임무는 주어진 작업에 적합한 도구를 찾는 것입니다. ;)
구체적인 질문을 구체적으로 명시하지 않으셨기 때문에 일반적인 질문으로 유지해야 합니다.
아마도 가장 쉬운 방법은 Perl을 직접 사용하는 것입니다.
cat file.txt | perl -wne '/([\w]+)/i and print $1'
man grep
grep에 대한 몇 가지 옵션 도 읽어보세요 .
-o, --only-matching
Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.
예를 들어 다음을 사용할 수 있습니다.
cat file.txt | grep -o '\w*'
그러나 최선의 방법은 실제로 문제에 따라 다릅니다. PHP를 좋아한다면 실제로 명령줄에서 PHP를 사용할 수도 있습니다.
답변3
이것은 Perl 프로그램에 모든 입력 줄을 공급/소비하는 데 perl
사용하는 또 다른 답변을 기반으로 합니다 .perl -ne
프로그램 에는 캡처 그룹이 포함된 정규 표현식이 포함된 명령문이 perl
있으며 if
, 일치하는 항목을 찾으면 이를 인쇄합니다.
캡처 그룹을 인쇄할 때 개행 문자를 추가합니다. 개행은 여러 일치 항목을 개행으로 구분하는 데 중요합니다. 그렇지 않으면 모든 결과가 같은 줄에 함께 혼합되어 예상치 못한/원치 않는 결과가 발생할 수 있습니다.
캡처링 그룹과 일치하는 여러 행을 얻는 경우 대부분의 경우 첫 번째 일치하는 행에만 관심이 있으므로 사용법은 입니다 head -1
.
다음 bash
스크립트는 이를 사용하여 입력 파일을 처리하고 추출된 결과를 변수에 저장하는 방법을 보여줍니다 value
.
cat file.txt # something="nice"
value=$(cat file.txt | perl -ne 'if (/something="([\w]+)"/) { print $1 . "\n" }' | head -1)
echo $value # nice