나는 "개행까지 tmp 및 이전 줄"을 인쇄하고 싶습니다. 저는 Unix를 처음 사용합니다.
예를 들면 다음과 같습니다.
AAA
CBH
VFh
GFD
DFC
VGF
HGD
TMP
JHG
TFD
PI1
98A
TMP
TMP
765
UBS
내가 원하는 출력은 다음과 같아야합니다
GFD
DFC
VGF
HGD
TMP
TFD
PI1
98A
TMP
TMP
답변1
사용 awk
:
$ awk -v RS='' -v ORS='\n\n' 'match($0,".*TMP") { print substr($0,1,RLENGTH) }' file
GFD
DFC
VGF
HGD
TMP
TFD
PI1
98A
TMP
TMP
이는 하나 이상의 빈 줄로 구분된 행 집합을 하나의 레코드로 처리합니다. 레코드가 정규식과 일치하면 .*TMP
일치하는 부분 뒤의 비트가 제거되고 레코드의 나머지 부분이 인쇄됩니다.
TMP
정규식을 현재 레코드와 .*TMP
일치 시킨 다음 해당 표현식과 일치하는 비트만 인쇄하여 substr()
마지막 발생 이후의 비트를 제거할 수 있습니다 . 정규식은 레코드의 시작부터 마지막 레코드까지 일치하며 TMP
함수 match()
는 변수를 RLENGTH
일치 길이로 설정합니다.
출력 레코드 구분 기호로 이중 개행 문자를 사용하므로 출력 끝에 추가 빈 줄이 표시됩니다.
파일이 다음과 같은 경우
AAA
CBH
VFh
GFD
DFC
VGF
HGD
tmp/some/path/here
JHG
TFD
PI1
98A
tmp/some/path/here
tmp/some/path/here
765
UBS
...그리고 로 시작하는 줄을 기반으로 동일한 유형의 변환을 수행한 tmp
다음 명령에 사용된 정규식을 수정하여 match()
끝에 있는 "-line"까지 개행 과 일치하도록 합니다 tmp
.
$ awk -v RS='' -v ORS='\n\n' 'match($0,".*tmp[^\n]*") { print substr($0,1,RLENGTH) }' file
GFD
DFC
VGF
HGD
tmp/some/path/here
TFD
PI1
98A
tmp/some/path/here
tmp/some/path/here
awk
상황이 어떤지 100% 확신할 수 없다는 점을 참고해 주세요.~해야 한다\n
괄호 표현식 내에서 해석되지만 awk
내가 액세스할 수 있는 모든 구현(OpenBSD awk
, OpenBSD mawk
및 GNE awk
)은 이를 개행 문자로 처리하는 것으로 보입니다.아니요두 개의 별도 문자로 \
및 n
.
답변2
텍스트를 뒤집어 정규식에서 정규식으로 정상적으로 인쇄한 다음 다시 역순으로 원래 순서를 얻으세요.
tac < file.txt | sed -n '/TMP/,/^$/p' | tac
답변3
첫 번째 것을 일치시킬 수 있다면 TMP
. 비어 있으면 RS
두 개 이상의 연속 \n
문자가 레코드 구분 기호로 사용되는 단락 모드가 됩니다.
$ # sub is used to remove everything after first occurrence of TMP
$ # return value of sub (0 if no match, 1 if match is found) determines
$ # if record should be printed or not
$ # use \nTMP\n to match only whole line
$ awk -v RS= 'sub(/TMP\n.*/, "TMP\n")' ip.txt
GFD
DFC
VGF
HGD
TMP
TFD
PI1
98A
TMP
끝까지 필요하다면 TMP
( GNU awk
because of gensub
) 또는perl
$ # use \nTMP\n to match only whole line
$ # same as: perl -00 -ne 'print if s/.*TMP\n\K.*/\n/s' ip.txt
$ awk -v RS= '/TMP/{print gensub(/(.*TMP\n).*/, "\\1", 1)}' ip.txt
GFD
DFC
VGF
HGD
TMP
TFD
PI1
98A
TMP
TMP
답변4
태그 지정을 위해 sed를 사용했으므로 표시된 대로 수행할 수 있습니다. 우리는 GNU sed를 사용하고 있습니다. 제가 이해한 바에 따르면, 텍스트 파일의 각 단락에서 tmp(소문자)로 시작하는 마지막 줄 이후의 모든 내용을 삭제하려고 합니다. 단락은 공백이 아닌 줄로 구성된 섬으로, 최소한 하나의 빈 줄로 다음 인스턴스와 구분됩니다.
sed -e '
/./{H;$!d;}
x;/\ntmp/!d
:chop
/\ntmp[^\n]*$/!s/\n[^\n]*$//
t chop
' file
단락을 축적하십시오. 경계(빈 줄 또는 eof)에 도달하면 단락 검사를 시작합니다. 개행 시작 부분에 tmp가 표시되지 않으면 이 섹션을 즉시 삭제합니다. 그렇지 않으면 para 처리를 중단하고 인쇄하는 tmp 줄이 보일 때까지 para 끝에서 줄을 자르기 시작합니다.
GNU awk를 사용하여 tge 단락 모드에서 작동하고 입력 필드 구분 기호를 개행 문자로 설정합니다. 끝부터 시작하여 필드를 확인하세요. tmp로 시작하는 필드가 보이면 해당 필드로 para를 좁히고 인쇄하여 단락을 완성합니다.
awk -F '\n' -v RS= -v OFS='\n' '
/(^|\n)tmp/ {
for(i=NF; i; i--) {
if ($i ~ /^tmp/) {
NF=i; NF++; print; break
}
}
}
' file
rindex는 문자열에서 하위 문자열이 끝에서 시작되는 위치를 알려줍니다. 따라서 rindex abd를 통해 마지막 tmp의 위치를 가져오고 해당 위치를 사용하여 다음으로 가장 가까운 개행 위치를 가져옵니다.
perl -p00e '
s/.*//s,next unless /^tmp/m;
s/\z/\n/;
my $p = 1+rindex($_, "\ntmp");
my $q = 1+index($_, "\n", $p);
substr($_, $q) = "\n";
' file