web-dev-qa-db-ja.com

awkを使用して、複数ではなく単一のスペースで行を分割する

形式を制御できない行を分割しようとしています。パラメーター7と8が欠落している可能性がある場合、それらはスペースに置き換えられるため、次のようになります。

field1 field2 field3 field4 field5 field6   field9

この状況では、現在、フィールド9はフィールド7として読み取られています。多くの検索により、以下が機能するはずであるが、機能していないと信じるようになりました。それはおそらく私の側のいくつかの小さな構文エラーですが、それを見つけることができないようです。

Word1=`echo $LINE | awk 'BEGIN { FS="[ ]" } ; { print $9 }'`
6

LINEパラメータは引用符で囲まれていないため、wordsplitting$LINEecho $LINEの展開時に発生し、awkが入力を受け取るまでに、7 words(シェルから見たとおり)すべて1つのスペースで区切られています。エコーが1つのWordとして出力するようにします(これも、シェルで確認できます)。これにより、awkが処理できるようになる前に、行の空白が壊されなくなります。これが、パラメーターを引用することによって妨げられます。

# How you want it to be given to awk:
$ printf '<%s> ' "$LINE"; echo
<field1 field2 field3 field4 field5 field6   field9> 
# Your attempt:
$ printf '<%s> ' $LINE; echo
<field1> <field2> <field3> <field4> <field5> <field6> <field9> 

余分な空白がどのようにfield6と9の間にあるかに注意してください。

展開を常に引用する必要があります。展開を引用するよりも、引用を引用しない方が、おそらく何かを壊します。

8
llua

可変入力長を処理するときにawkで非常に役立つパラメーターは、フィールド数であるNFです。

lastword=`echo $LINE | awk '{ print $NF }'`

欠落している列に関係なく、常に最後の列が出力されます。真ん中のいくつかのフィールドが欠けている場合、最後のフィールドから数えることもかなりうまくいきます。

例のように、欠落/空の列がスペースで埋められたサンプルファイル:

line1 field1 field2 field3 field4 field5 field6 field7 field8 field9
line2 field1 field2 field3 field4 field5 field6  field8 field9
line3 field1 field2 field3 field4 field5   field8 field9

そして

awk '{print $1 " " $2 " " $(NF-1) " " $NF}' file

    line1 field1 field8 field9
    line2 field1 field8 field9
    line3 field1 field8 field9
5
HBruijn

ksh93で行うには:

set -f
IFS='  ' # two spaces
set -- $LINE
printf '%s\n' "$9"

スペースを2倍にすると、zshのように、スペースのシーケンスが1つと見なされ、先頭と末尾のスペースが無視されるという特殊な動作が削除されます。

2