Pattern.txt라는 파일에 단어 목록이 있습니다. 목록의 모든 단어가 포함된 입력 스트림의 단락을 검색해야 합니다. 단락의 단일 단어(foo)에 대해서는 일반적으로 sed 코드를 사용합니다.
sed '/./{H;$!d;}; x;/foo/!d'
하지만 단어 목록으로 이 작업을 수행하는 방법을 모르겠습니다.
답변1
GNU awk 사용:
$ cat patterns.txt
foo
bar
baz
$ cat file
first paragraph foo bar
second baz bar foo
third
fourth foo baz bar
fifth baz foo
이는 cat file
입력 스트림을 나타냅니다.
$ cat file | gawk '
NR == FNR {pattern[++n] = $0; next}
ENDFILE {RS = ""; ORS = "\n\n"}
{for (i = 1; i <= n; i++) if ($0 !~ pattern[i]) next; print}
' patterns.txt - # note the trailing hyphen
second baz bar foo
fourth foo baz bar
RS = ""
빈 줄로 구분된 단락을 레코드로 읽으려면 awk를 변경하세요.
답변2
그리고 perl
:
perl -ne '
BEGIN {chomp(@patterns = <STDIN>); $/ = ""}
for $p (@patterns) {next LINE unless /$p/}
print' -- your-file < patterns.txt
sed
패턴은 in 과 같은 기본 정규식 이나 in 과 같은 확장 정규식이 아닌 perl 정규식으로 해석됩니다 awk
. 대부분은 확장 정규식과 이전 버전과 호환됩니다.
그러나 .
기본적으로 줄바꿈은 일치하지 않습니다. s
플래그를 추가( /$p/s
대신 /$p/
)하여 변경할 수 있습니다.
그 외에도 그들이 일하고 있다면 awk
아마도 일하고 있을 것입니다 perl
. BRE 또는 ERE에 대한 많은 확장 기능이 있으며 그 중 일부는 단락 내 일치에 매우 유용합니다. 예를 들어 (?m)^foo$
는 에 대한 줄이 포함된 단락과 정확히 일치합니다 foo
. Perl 정규식은 사실상의 표준이 되었으며, 그 확장의 대부분은 Python, PHP 및 PCRE 또는 PCRE2를 사용하는 모든 언어를 포함한 대부분의 최신 프로그래밍 언어에서 사용할 수 있습니다.
답변3
사용행복하다(이전 Perl_6)
~$ raku -e 'for slurp.split("\n\n") { .put if (/foo/ & /bar/ & /baz/) };' file
또는
~$ raku -e 'for slurp.split("\n\n") { .put if all(/foo/, /bar/, /baz/) };' file
Raku는 Perl 계열의 프로그래밍 언어입니다. 위에서는 파일을 slurp
편집(즉, 한 번에 읽기)하여 단락별로 구분합니다 \n\n
. 이러한 단락 요소는 다음을 사용하여 반복 for
되며 if
적절한 정규식과 일치합니다( &
부울 사용).그리고연산자), 단락이 끝났습니다 put
. 두 번째 코드 예제는 첫 번째 코드 예제와 유사하지만 Raku의 새로운 "Junction" 연산자가 포함되어 있습니다 all
. Raku에는 all
, any
, one
및 4개의 "Junction" 연산자가 있습니다 none
.
참고: 단락이 두 개 이상의 줄 바꿈으로 구분된 경우 split
와 같은 정규식 매개변수와 함께 사용하세요 .split( / \n ** 2..* / )
.
입력 예(@glenn_jackman 덕분에):
first paragraph foo bar
second baz bar foo
third
fourth foo baz bar
fifth baz foo
예제 출력:
second baz bar foo
fourth foo baz bar
"패턴"을 입력 파일로 사용: 위의 패턴 일치를 작성하지 않으려면 위 코드 앞에 공백으로 구분된 목록을 추가할 수 있습니다("단어 참조" 옵션은 하단의 첫 번째 링크 참조).
~$ raku -e 'my @words = <foo bar baz> ; for slurp.trim.split("\n\n") { .put if .match: all @words };' file
또는 파일에서 직접 "패턴"을 읽을 수 있습니다(@glenn_jackman의 답변에서와 같이 한 줄에 하나의 "패턴"을 가정).
~$ raku -e 'my @words = "patterns.txt".IO.lines; for slurp.trim.split("\n\n") { .put if .match: all @words };' file
테스트 모드 입력 파일로 공백으로 구분된 "단어"만 사용하려는 경우 위 입력 줄을 다음과 같이 단순화할 수 있습니다.
my @words = "patterns.txt".IO.words;
https://docs.raku.org/언어/quoting
https://docs.raku.org/type/Junction
https://raku.org