awk를 사용하세요

awk를 사용하세요

아래에 샘플 텍스트 파일(test_long_sentence.txt)이 있고 불필요한 데이터를 제외하고 test1이 포함된 모든 줄을 grep하고 싶습니다.

견적이 끝나기 전에 어떻게 데이터를 수집할 수 있나요?

test_long_sentence.txt

This is some unwanted data blah blah blah

20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"

This is some unwanted data blah blah blah

20  /test1/theme="Halloween"

주문하다:

grep "test1" test_long_sentence.txt

실제 출력:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
20  /test1/type="Western"
20  /test1/theme="Halloween"

예상 출력:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

추신: 나는 test_long_sentence.txt 편집을 제어할 수 없습니다. 그러니 저에게 한 줄로 편집해달라고 요청하지 마세요.

답변1

awk를 사용하세요

$ awk '/test1/{line=$0; while (!(line ~ /[^\\]".*[^\\]"/)) {getline; line=line "\n" $0}; print line}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

/test1/조건입니다. 현재 줄에 regex 와 일치하는 내용이 포함되어 있으면 test1중괄호로 묶인 명령이 실행됩니다. 이러한 명령은 다음과 같습니다.

  • line=$0

    현재 라인의 내용은 "line" 변수에 저장됩니다.

  • while (!(line ~ !/[^\\]".*[^\\]"/)) {getline; line=line "\n" $0}

    현재 콘텐츠에 line이스케이프 처리되지 않은 두 개의 따옴표가 포함되어 있지 않으면 다음 줄을 가져와 via getline에 추가합니다.lineline=line "\n" $0

  • print line

    이제 변수에는 line이스케이프 처리되지 않은 두 개의 따옴표가 포함되어 있으며 이를 인쇄합니다.

명령을 여러 줄에 걸쳐 분산시키려는 경우 위와 동일한 명령을 다음과 같이 작성할 수 있습니다.

awk '
    /test1/{
        line=$0
        while (!(line ~ /[^\\]".*[^\\]"/)) {
            getline
            line=line "\n" $0
        }
        print line
    }' sentence.txt 

sed 사용

$ sed -n '/test1/{:a; /[^\\]".*[^\\]"/{p;b}; N; ba}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

작동 방식:

  • -n

    이는 명시적으로 요청하지 않는 한 sed가 아무것도 인쇄하지 않도록 지시합니다.

  • /test1/{...}

    포함된 line에 대해 test1다음과 같이 중괄호로 묶인 명령을 실행합니다.

    • :a

      이는 label 을 정의합니다 a.

    • /[^\\]".*[^\\]"/{p;b}

      패턴 공간에 현재 이스케이프되지 않은 두 개의 따옴표가 포함되어 있으면 패턴 공간을 인쇄한 p다음 나머지 명령어를 건너뛰고 b다음 줄에서 시작합니다.

    • N

      여기에 도달하면 현재 이스케이프 처리되지 않은 따옴표가 두 개 없다는 의미입니다. 패턴 공간으로 다음 줄을 읽어 들입니다.

    • ba

      레이블로 돌아가서 a해당 레이블 다음에 명령을 반복합니다.

답변2

이는 해당 특정 파일에 awk대신 적용됩니다.grep

awk 'NR==3,NR==7;NR==11' test_long_sentence.txt

나중에 이 문제를 해결하려면 cat -n파일을 실행하여 포함하고 제외할 줄을 확인할 수 있습니다.

답변3

이것은 입력에서 연속적인 라인을 연결하는 간단한 Perl 스크립트입니다. 다음을 가정합니다.

  • 연속된 줄은 단일 공백 ​​문자로 연결됩니다.

  • "라인"은 숫자와 공백으로 시작하는 입력 라인으로 시작하여 다음까지 계속됩니다.

    • 빈 이미지
    • 다른 줄은 숫자와 공백으로 시작됩니다.
  • 빈 줄과 그 사이의 모든 줄은 무시됩니다(즉, 삭제됩니다).

이는 실제 입력 파일과 완벽하게 일치하지 않을 수 있지만 질문에 제공된 샘플 입력과 일치합니다. 입력 내용에 맞게 필요에 따라 코드를 수정합니다.

#!/usr/bin/perl

my $skip=1;  # start with skip = true.
my $line='';

while(<>) {
  chomp;

  if (m/^\d+\s+/) { # / this comment is only here to fix SE\'s syntax highlighting
    $skip=0;
    print $line,"\n" if ($line);
    $line = $_;

 } elsif (m/^\s*$/) {
    if ($line ne '') { print $line, "\n"; $line = ''};
    $skip = 1 - $skip;

  } elsif (! $skip) {
    $line .= " $_";
 };
};

예를 들어 ./join-lines.pl실행 파일을 만들고 chmod +x ./join-lines.pl다음과 같이 실행하십시오.

$ ./join-lines.pl test_long_sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly, Babies, \"Witch\", Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

그런 다음 필요에 따라 이를 grep다른 도구 에 공급할 수 있습니다.

현재 샘플 입력의 경우 모든 샘플 행에 "test1"이 포함되어 있으므로 의 출력 ./join-lines.pl test_long_sentence.txt | grep test1(가능한 일치 색상 제외 grep)은 위의 출력과 동일합니다. 다른 일치 항목을 찾기 위해 더 유용하게 grep할 수 있습니다. 예를 들면 다음과 같습니다.

$ ./join-lines.pl test_long_sentence.txt | grep Witch
20  /test1/target="Adults, \"Goblins\", Elderly, Babies, \"Witch\", Faries"

정확히 동일한 입력을 재현할 수 있어야 하는 경우(공백 및 원하지 않는 줄 제외) 줄을 공백으로 연결하는 대신 " ===NL=== "TAB과 같이 꼭 필요한 문자나 더 긴 문자열(예: 절대로 사용하지 않는 문자)을 사용하세요. 입력에 나타납니다. 예를 들어

  } elsif (! $skip) {
    $line .= "\t$_";
 };

또는

  } elsif (! $skip) {
    $line .= " ===NL=== $_ ";
 };

그런 다음 연결 문자열을 다시 개행 문자로 변환할 수 있습니다 sed(예: 탭을 연결 문자로 사용).

$ ./join-lines.pl test_long_sentence.txt  | grep Witch | sed -e 's/\t/\n/g'
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"

더 긴 문자열을 사용하여 줄을 연결하는 또 다른 예:

./join-lines.pl test_long_sentence.txt  | grep Witch | sed -e 's/ ===NL=== /\n/g'

관련 정보