チルダ(〜)で区切られたフィールドの合計を計算する必要があります。私が経験している問題は、私のデータにも区切り文字エスケープがあることです。
はい
1~CEO~ashok\~kumar~1000
上記の3番目のフィールドに示すように、避けたい区切り文字をエスケープしました。次のコマンドを実行していますが、問題は処理されません。
$ cat test.out|awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
test.out
データが次のとおりです。
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
したがって、私の出力は4000でなければなりません。しかし、現在私の命令では3000しか得られません!
答え1
処理する前に、エスケープ区切り文字を別のものに変更してくださいawk
。これは次の方法で行うことができますsed
。
$ cat test.out| sed 's/\\~/=/g' | \
awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
4000
そして、しばしばそうであるように、以下を行う必要もありませんcat
。
$ sed 's/\\~/=/g' test.out | awk -F'~' 'BEGIN {sum=0} {sum+=$4} END{print sum}'
答え2
未使用の代替方法は次のとおりですawk
。
$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+ | bc
4000
上記のコードは、3番目の列でエスケープされたチルダをsed
置き換えます。\~
次に、cut
を使用して数字の4番目の列を選択し、プラス記号()で区切るように再設定できます+
。
$ sed 's/\\~/=/g' test.out | cut -d"~" -f4 | paste -sd+
1000+2000+1000
その後、この文字列はバイナリ計算機に入力され、bc
合計されます。
答え3
エスケープを処理するための一般的なアプローチは、perl
逆追跡演算子なしでPCREとシフト正規表現演算子を組み合わせることです。 GNUは次のとおりですgrep
。
grep -Po '(?>(?:\\.|.)*?~){3}\K(?:\\.|[^~])*' << \EOF
1~CEO~ashok\~kumar~1000
2~CFO~Ranjan~2000
3~CEO~kumar~1000
4~field2~field3\\~10000~field5-note-the-escaped-backslash-not-tilde
5~a\~b\~c\~no-4th-field-here
EOF
これは作る:
1000
2000
1000
10000
(普段に追加できますawk '{s+=$0};END{print s}'
)。
GNUを使用すると、sed
次のこともできます。
sed -rn 's/((\\.|[^\~])*~){3}((\\.|[^~])*).*/\3/p'
GNUを使用すると、フィールドをエスケープ文字やチルダではなく、文字またはバックスラッシュ文字のシーケンスとして定義awk
できます。FPAT
awk -v FPAT='(\\\\.|[^\\\\~])*' '{print $4}'
答え4
これはawkでは少し扱いにくいです(区切り記号を変更するためにソースコードを前処理することができますが、入力には現れない他の文字や文字シーケンスを知る必要がある場合を除きます)。あなたができることの1つは、行全体を読み、次に改行文字を区切り文字として使用するように行を変更することです(改行は行には現れない唯一のものです)。
awk 'BEGIN {FS="\n"}
{
gsub("~", "\n");
gsub("\\\n", "~");
gsub("\\\\", "\\");
$0 = $0;
print $4;
}'