sed/awk를 사용하여 일치하는 패턴을 인쇄하는 방법은 무엇입니까? (grep을 사용하여 이 작업을 수행할 수 있습니다)

sed/awk를 사용하여 일치하는 패턴을 인쇄하는 방법은 무엇입니까? (grep을 사용하여 이 작업을 수행할 수 있습니다)

11개의 라벨을 인쇄하려면 awk 또는 sed와 WHILE 루프를 사용하면 됩니다.

Order:479959,60=20130624-09:45:02.046|35=D|11=884|38=723|21=1|1=30532|10=085|59=0|114=Y|56=MBT|40=1|43=Y|100=MBTX|55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=20130624-09:45:02.046|
Order:24780,100=MBTX|43=Y|40=1|34=388|553=2453|52=2013062409:45:02.046|9=205|49=11342|54=1|8=FIX.4.4|55=/GCQ3|11=405|35=D|60=20130624-09:45:02.046|56=MBT|59=0|114=Y|10=085|21=1|38=470|1=30532|
Order:799794,55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=2013062409:45:02.046|40=1|43=Y|100=MBTX|38=350|21=1|1=30532|10=085|59=0|114=Y|56=MBT|60=20130624-09:45:02.046|35=D|11=216|
Order:72896,11=735|35=D|60=2013062409:45:02.046|56=MBT|59=0|114=Y|10=085|1=30532|38=17|21=1|100=MBTX|43=Y|40=1|553=2453|9=205|52=20130624-09:45:02.046|34=388|8=FIX.4.4|54=1|49=11342|55=/GCQ3|

출력은 다음과 같아야 합니다.

Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216

답변1

루프가 필요하지 않습니다.

$ sed 's/^.*[,|]11=\([^|]*\).*$/client id = \1/' data.in
client id = 884
client id = 405
client id = 216
client id = 735

11편집 스크립트는 레이블( 또는 11=앞에 오는 ) 을 찾고 전체 줄을 숫자 뒤에 오는 텍스트로 바꿉니다 (실제로는|,client id =11=아무것11=라인 의 끝 또는 라인을 따르십시오 |.)

업데이트(새 질문 사양 이후):

이는 다음과 같습니다 (GNU 및 GNU uglyscript.sh필요 ).sedawk

#!/bin/sh
tr ',|' '\n' |
awk -vRS="\n\n" '{ print | "sort -r"; close("sort -r") }' |
tr '\n' '|' |
sed 's/|Order/\nOrder/g' |
sed 's/^Order:\([^|]*\).*|\(38=[^|]*\).*|11=\([^|]*\).*$/Orderid-\1 \2 Clientid=\3/'
echo
  1. 첫 번째는 tr입력 데이터의 모든 행을 열로 변환합니다. 원시 행은 출력에서 ​​빈 행(2개의 줄 바꿈)으로 구분됩니다.
  2. awk각 행 세트를 사전식 역순으로 개별적으로 정렬합니다("순서"가 먼저 나오도록).
  3. tr다음을 포함하는 두 번째 항목은 sed행을 다시 그룹화하지만 이제 열은 정렬된 순서로 정렬됩니다. tr모든 줄 바꿈을 하나의 문자로 바꾸고 |문자열 이 sed있는 줄을 끊습니다.|Order
  4. 마지막 솔루션은 sed원래 솔루션과 유사하지만 라인에서 더 많은 것을 캡처합니다.
  5. 마지막 것은 echo출력 끝에 줄 바꿈이 있는지 확인하는 것입니다.

열이 정렬되지 않았으므로 위의 1~3단계가 필요합니다. 11=예를 들어 포함된 열은 줄의 어느 곳에나 나타날 수 있으므로 sed단일 스크립트를 통해 실행하기가 매우 어렵습니다.

3단계 이후의 데이터는 다음과 같습니다.

Order:479959|9=205|8=FIX.4.4|60=20130624-09:45:02.046|59=0|56=MBT|55=/GCQ3|553=2453|54=1|52=20130624-09:45:02.046|49=11342|43=Y|40=1|38=723|35=D|34=388|21=1|1=30532|11=884|114=Y|10=085|100=MBTX
Order:24780|9=205|8=FIX.4.4|60=20130624-09:45:02.046|59=0|56=MBT|55=/GCQ3|553=2453|54=1|52=2013062409:45:02.046|49=11342|43=Y|40=1|38=470|35=D|34=388|21=1|1=30532|11=405|114=Y|10=085|100=MBTX
Order:799794|9=205|8=FIX.4.4|60=20130624-09:45:02.046|59=0|56=MBT|55=/GCQ3|553=2453|54=1|52=2013062409:45:02.046|49=11342|43=Y|40=1|38=350|35=D|34=388|21=1|1=30532|11=216|114=Y|10=085|100=MBTX
Order:72896|9=205|8=FIX.4.4|60=2013062409:45:02.046|59=0|56=MBT|55=/GCQ3|553=2453|54=1|52=20130624-09:45:02.046|49=11342|43=Y|40=1|38=17|35=D|34=388|21=1|1=30532|11=735|114=Y|10=085|100=MBTX|

실행하세요:

$ ./uglyscript.sh <data.in
Orderid-479959 38=723 Clientid=884
Orderid-24780 38=470 Clientid=405
Orderid-799794 38=350 Clientid=216
Orderid-72896 38=17 Clientid=735

답변2

"깨끗한" awk 솔루션

관심이 있다면 awk출력 버전이 포맷된 일회성 명령이 있습니다(비록 꽤 좋은 작업처럼 보이지만 sed).

awk -F'\\||,' '{
                   for (i=1;i<NF+1;i++) {
                     if ($i ~ /11=.*/) {
                       split($i, a, "=")                           
                     }
                     if ($i ~ /Order:.*/) {
                       split($i, b, ":")
                     }
                     if ($i ~ /38=.*/) {
                       split($i, c, "=")
                     }
                   }
                   printf "Orderid-%-10s 38= %-8s Clientid=%s\n", b[2], c[2], a[2]
                 }' < infile.txt

awk, sed또는 를 절대적으로 사용하고 싶지 않고 tr루프 while 루프를 절대적으로 원하는 경우 주석에서 이미 언급했듯이 이는 매우 나쁜 습관이라는 점에 유의하십시오. 해석의 폭이 넓다너무 끔찍해여기.


"이것을 하지 마세요" 솔루션

이제 우리는 약간의 면책 조항을 만들었으므로 bash 문자열 조작만을 사용하여 while 루프에서 출력을 얻는 방법이 있습니다(물론 스크립트 형식에서는bash에서만 작동합니다):

while read line; 
do
  x=${line#*11=}
  x=${x%%|*}
  y=${line#*:}
  y=${y%%,*}
  z=${line#*38=}
  z=${z%%|*}
  echo "Orderid-$y 38= $z Clientid=$x"
done < infile.txt

귀하의 구체적인 예에서는 작동하지만제발"실제" 상황에서는 이 작업을 수행하지 마세요. 모든 쉘의 기본 아이디어는 "외부 도구에 대한 호출이 적을수록 좋다"입니다. 따라서 이상적으로는 내 awk 예처럼 한 번의 호출로 수행할 수 있다면 그렇게 하십시오. awk가 로드됩니다한 번그런 다음 모든 작업이 C로 수행되는데 이는 셸에 비해 매우 빠릅니다.


내 대답은 bash에서 문자열 조작이 어떻게 작동합니까?

  • ${string#pattern}: 문자열의 왼쪽부터 삭제가장 짧은패턴을 일치시킵니다. 따라서 이와 같은 패턴을 넣으면 *a모든 것이 다음에 따라 달라집니다.첫 번째"a" 문자(포함)가 문자열에서 제거됩니다. 동일한 구문을 사용하지만 2개의 "#"을 사용하는 경우 for의 일치는 pattern최대한 탐욕스러워지며 문자열에서 마지막 "a" 문자까지 모든 내용이 제거됩니다. 예:

    $ test="alakazam"; echo ${test#*a}; echo ${test##*a};
    lakazam
    m
    
  • ${string%pattern}: 동일하게 작동하지만 오른쪽에서 시작됩니다. 이전 예를 사용하여 설명합니다.

    $ test="alakazam"; echo ${test%a*}; echo ${test%%a*};
    alakaz
                 #no output here: the whole string is matched by pattern
    

관련 정보