아래에 샘플 텍스트 파일(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
이스케이프 처리되지 않은 두 개의 따옴표가 포함되어 있지 않으면 다음 줄을 가져와 viagetline
에 추가합니다.line
line=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'