パイプ記号|
が含まれているときに文字列を分割する方法。それらを配列になるように分割したい。
私は試した
echo "12:23:11" | awk '{split($0,a,":"); print a[3] a[2] a[1]}'
これはうまくいきます。私の文字列が"12|23|11"
のようなものであれば、どうやってそれらを配列に分割するのですか?
やってみました:
echo "12|23|11" | awk '{split($0,a,"|"); print a[3],a[2],a[1]}'
文字列をawk
の配列に分割するには、関数 split()
を使います。
awk '{split($0, a, ":")}'
# ^^ ^ ^^^
# | | |
# string | delimiter
# |
# array to store the pieces
区切り文字が指定されていない場合は、デフォルトでスペースが使用されるFS
が使用されます。
$ awk '{split($0, a); print a[2]}' <<< "a:b c:d e"
c:d
例えば:
のようにセパレータをつけることができます。
$ awk '{split($0, a, ":"); print a[2]}' <<< "a:b c:d e"
b c
これはFS
で設定するのと同じです。
$ awk -F: '{split($0, a); print a[1]}' <<< "a:b c:d e"
b c
Gawkでは、正規表現としてセパレータを指定することもできます。
$ awk '{split($0, a, ":*"); print a[2]}' <<< "a:::b c::d e" #note multiple :
b c
さらに、4番目のパラメータを使用して、区切り文字が各ステップで何をしているのかも確認できます。
$ awk '{split($0, a, ":*", sep); print a[2]; print sep[1]}' <<< "a:::b c::d e"
b c
:::
GNU awkのmanページ を引用しましょう。
split(string、array [、fieldsep [、seps]])
fieldsepで区切られたstringの部分に分割し、arrayの部分とseps配列の区切り文字列を格納します。最初の部分は
array[1]
に、2番目の部分はarray[2]
に格納されます。 3番目の引数の文字列値fieldsepは、分割する場所を記述する正規表現です[string(FSと同じように正規表現にすることができます)入力レコードを分割する場所)。 fieldsepを省略した場合は、FSの値が使用されます。split()
は作成された要素の数を返します。 sepsはgawk
の拡張子で、seps[i]
はarray[i]
とarray[i+1]
の間の区切り文字列です。 fieldsepが単一スペースの場合、先頭の空白はseps[0]
に、末尾の空白はseps[n]
になります。ここで、nはsplit()
の戻り値です(つまり、配列の要素).
もっと具体的にしてください! 「うまくいかない」とはどういう意味ですか?正確な出力(またはエラーメッセージ)、あなたのOSとawkのバージョンを投稿してください:
% awk -F\| '{
for (i = 0; ++i <= NF;)
print i, $i
}' <<<'12|23|11'
1 12
2 23
3 11
あるいは、splitを使って:
% awk '{
n = split($0, t, "|")
for (i = 0; ++i <= n;)
print i, t[i]
}' <<<'12|23|11'
1 12
2 23
3 11
編集:on Solaris処理するにはPOSIX awk(/ usr/xpg4/bin/awk)を使用する必要があります。正しく4000フィールド。
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
不要なfork
およびexec
system呼び出しを呼び出すので、echo "..." | awk ...
ソリューションは好きではありません。
私は少しひねりを加えたDimitreのソリューションを好む
awk -F\| '{print $3 $2 $1}' <<<'12|23|11'
または少し短いバージョン:
awk -F\| '$0=$3 $2 $1' <<<'12|23|11'
この場合、出力レコードはまとまっていますが、これは本当の条件なので、印刷されます。
この特定のケースでは、stdin
のリダイレクトは awk 内部変数を設定することで回避できます。
awk -v T='12|23|11' 'BEGIN{split(T,a,"|");print a[3] a[2] a[1]}'
私は ksh をかなり長い間使っていましたが、 bash ではこれは内部の文字列操作で管理できました。前者の場合、元の文字列は内部ターミネータによって分割されます。後者の場合、文字列には常に1文字の区切り文字で区切られた数字のペアが含まれていると想定されます。
T='12|23|11';echo -n ${T##*|};T=${T%|*};echo ${T#*|}${T%|*}
T='12|23|11';echo ${T:6}${T:3:2}${T:0:2}
すべての場合の結果は
112312
実際にはawk
には 'Input Field Separator Variable'という機能があります link 。これが使い方です。実際には配列ではありませんが、内部の$変数を使用しています。単純な文字列を分割する場合は簡単です。
echo "12|23|11" | awk 'BEGIN {FS="|";} { print $1, $2, $3 }'
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
うまくいくはずです。
冗談で? :)
echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
はどうですか
これは私の出力です:
p2> echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
112312
それで結局それは働いていると思います。