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
必要です)。sed
awk
#!/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
- 最初は、
tr
入力データのすべての行を列に変換します。生の行は、出力から空行(2行改行)に分けられます。 awk
各行セットを辞書式の逆順に個別に並べ替えます(「順序」が最初に出るように)。tr
次を含む2番目の項目はsed
行を再グループ化しますが、列はソートされた順序でソートされます。tr
すべての改行を1文字に置き換え、文字列を含む行を|
破棄sed
します。|Order
- 最後の解決策は
sed
元の解決策と似ていますが、行でより多くをキャプチャします。 - 最後は、
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の例のように1回の呼び出しで実行できる場合はそうします。 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