다음 형식의 큰 .txt 파일이 있습니다.
Pin name="AR_OP" status="f"
Pref x=997.6800 y=2327.0400 side=N width=0.0400 depth=0.3750 /
Layer id=1
--
Pin name="AW_OP" status="f"
Pref x=997.6800 y=2327.0400 side=S width=0.0400 depth=0.3750 /
Layer id=2
내가 원하는 출력은 다음과 같습니다.
Pin name="AR_OP" side=N
Pin name="AW_OP" side=S
검색하고 싶은 부분마다핀 이름내가 원하는 핀 이름과 일치합니다.옆같은 줄에. 누구든지 도울 수 있습니까?
답변1
모든 공백을 개행 문자로 바꾸고 , Pin
또는 로 시작하는 name=
줄을 빼냅니다 side=
. 이렇게 하면 세 그룹으로 구성된 라인이 제공됩니다. 세 줄로 구성된 각 세트를 공백을 구분 기호로 사용하여 한 줄로 다시 포맷합니다.
$ tr ' ' '\n' <file | grep -e '^Pin$' -e '^name=' -e '^side=' | paste -d ' ' - - -
Pin name="AR_OP" side=N
Pin name="AW_OP" side=S
이는 모든 값에 공백이 포함되어 있지 않다고 가정합니다.
문서가 다음과 같은 XML 문서로 시작되었다고 가정합니다.
<?xml version="1.0"?>
<root>
<Pin name="AR_OP" status="f">
<Pref x="997.6800" y="2327.0400" side="N" width="0.0400" depth="0.3750"/>
<Layer id="1"/>
</Pin>
<Pin name="AW_OP" status="f">
<Pref x="997.6800" y="2327.0400" side="S" width="0.0400" depth="0.3750"/>
<Layer id="2"/>
</Pin>
</root>
그러면 데이터는 다음에서 더 잘 얻을 수 있습니다.이것후처리 변형에는 텍스트 처리 도구 대신 XML 인식 도구를 사용하십시오.
예를 들어,
xmlstarlet select --template \
--match '//Pin' --output 'Pin' \
--output ' name="' --value-of '@name' --output '"' \
--output ' side="' --value-of 'Pref/@side' --output '"' \
-nl file
이는 입력 문서에서 모든 노드를 xmlstarlet
찾는 데 사용됩니다 . Pin
그런 다음 이를 반복하여 해당 name
속성과 Pref
하위 노드의 속성을 요청된 형식으로 출력합니다.side
유사한 방법그리고xq
, 잘 알려진 JSON 파서 주변의 jq
XML 파서 래퍼 :
xq -r '.root.Pin | map("Pin name=\"\(."@name")\" side=\"\(.Pref."@side")\"")[]' file
답변2
가정된 값에는 side
항상 하나 이상의 대문자가 포함됩니다.
awk '{
if (match($0, /Pin name="[^"]+"/)) {
printf "%s ", substr($0, RSTART, RLENGTH)
next
}
if (match($0, /side=[A-Z]+/)) {
printf "%s\n", substr($0, RSTART, RLENGTH)
}
}' file
이는 일치하는 부분과 공백 또는 개행 문자만 출력합니다.
답변3
펄 사용:
$ perl -lne 'if (/^\s*(Pin name="[^"]*").*/) {
$pin = $1;
$_ = <>;
if (/(side=.)/) {
$side = $1;
printf "%s %s\n", $pin, $side;
}
}' input.txt
Pin name="AR_OP" side=N
Pin name="AW_OP" side=S
영어로:
현재 줄이 일치하면 Pin name"[^"]*"
캡처 그룹( $1
)을 사용하여 이를 추출하고 변수에 저장한 $pin
후 다음 줄( $_ = <>;
)을 읽습니다. "side=."가 포함되어 있으면 변수로 추출 $side
하고 사이에 공백을 두고 $pin과 $side를 인쇄합니다. 다른 모든 입력 라인은 무시됩니다.
또 다른 변형은 다음과 같습니다.
$ perl -lne 'if (/^\s*(Pin name="[^"]*").*/) {
$pin=$1;
($side = <>) =~ s/^.*(side=.).*/\1/;
printf "%s %s", $pin, $side if $side =~ /side=/
}' input.txt
Pin name="AR_OP" side=N
Pin name="AW_OP" side=S
영어로:
현재 줄이 "핀 이름..."과 일치하면 추출되어 $pin 변수에 저장됩니다. 그런 다음 다음 줄을 ($side = <>)
변수로 읽어 들여 $side
$side를 수정하여 "side="를 제외한 모든 항목을 제거합니다. ( =~ s/^.*(side=.).*/\1/;
) 그런 다음 둘 다 인쇄하십시오.만약에 $side
포함하다 /side=/
.
그건 그렇고, 그 ($side = <>) =~ s/^.*(side=.).*/\1/;
줄은 변수를 할당한 다음 바꾸기 작업을 사용하여 즉시 수정하는 데 유용한 perl 관용구의 예입니다( s///
. tr///
도 작동합니다). 이는 $side=<>
다음 줄을 $side로 읽은 다음 $side =~ s/^.*(side=.).*/\1/;
$side를 수정하는 두 가지 명령문과 동일합니다 .
할당 주위의 괄호는 중요합니다. 그렇지 않으면 변수에 성공/실패 또는 대체 작업 수가 포함됩니다(그러나 할당의 오른쪽이 =
수정 가능한 변수인 경우에만 해당). 그렇지 않은 경우 파일 핸들과 같이 수정 불가능한 변수인 경우 , 그러면 그것은 단지 문법적 오류입니다).