私の店には、誰かが以前に書いたAWKコードスニペットがありますが、文書化されていないので、それを解釈する方法がわかりません。
awk -F'~"' ' {gsub(/~/, " ", $3); print $1"~\""$2"~\""$3"~\""$4}' INFILE.dat > OUTFILE.dat
想像する:
区切られたテキストファイルには、~
以下の12列があります。
本質的に文字であるデータは、列3、9、10などの二重引用符で囲まれています。
1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000~2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556
^^^^^^^^^^^
列9にはフィールド区切り文字をvarchar(100)
含めることができます~
。
上記のawkコードは、~
列9を空白に部分的に変換しますgsub()
。
このコードがどのように機能するかを正確に伝えることができる人はいますか?
入力ファイルはINFILE.dat
。出力ファイルはOUTFILE.dat
。
予想される出力に関して変更する唯一のことは、9番目の列のデータです。間にスペースを使用する~
必要があります。"2000~2001"
出力ラインは次のとおりです。
1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000 2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556
^^^^^^^^^^^
答え1
既存のコードは不必要に複雑です。特定のデータの特定のフィールドにのみ適用されるように脆弱でハードコーディングされているため、理解しにくく、実際に廃棄する必要があります。
awkを使用して二重引用符内の文字または文字列を他の文字または文字列に置き換える慣用的な方法は次のとおりです。
$ awk 'BEGIN{FS=OFS="\""} {for (i=2; i<=NF; i+=2) gsub(/~/," ",$i)} 1' file
1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000 2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556
これは行を"
区切られたフィールドに分割するので、すべての偶数フィールドは引用符の間のフィールドです("a"~"b"
= 1)null
2)a
3) ~
4)b
5)null
)したがって、対応する偶数フィールドは私たちが作業しているフィールドです。
それが(または元のスクリプト)何をしているのかわからない場合は、マンページを参照してから使用されたさまざまな変数の値が何であるかを確認するために、いくつかの印刷ステートメントを追加するだけです。
データは基本的にCSVのサブセットですが、~
代わりに,
区切り文字として使用する方法については、以下を参照してください。awkを使用してcsvを効率的に解析する最も強力な方法は何ですかawkを使用してCSVを処理する方法を学びます。
awkを使用するには、awkについて知っておくべきことがいくつかあります。元のスクリプトとこの新しいスクリプトは、awk言語の非常に基本的なコンポーネントを使用します。 Arnold Robbinsの「Effective AWKプログラミング、第5版」の本を入手して、少なくとも基本を学び、他のものが必要な場合に準備できるようにします。コンテンツを編集するときに便利に使用してください。
答え2
ㅏ人類ファイルが~
区切られていると思うかもしれませんが、awk式ではファイルが一連の2文字に分かれていると思います~"
。したがって、あなたが提供したサンプルラインには以下が含まれます。4つフィールド:
-
1235678~2005-04-13-13.49.42.149512
-
10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29
-
2000~2001"
-
N"~0.00~9999.63~2005-04-13-13.49.42.149556
したがって、アプリケーションはgsub(/~/, " ", $3)
そのうちの(単一)を空白に置き換えます。この文字列はソースを置き換えます。外部引用符は文字列構文であり、内部引用符を保護するにはバックスラッシュが必要です。個人的には、私はjustまたは印刷目的を使用することを避けたいと思います。~
2000~2001"
"~\""
FS
print $1 FS $2 FS $3 FS $4
みんな使用されたフィールド
awk -F'~"' 'BEGIN{OFS=FS} {gsub(/~/, " ", $3)} 1'
しかし、このアプローチは脆弱に見えます。 9番目の「実際の」フィールドが3番目に区切られたフィールド内に存在することを確認できますか~"
?引用符付きフィールドに区切り文字が存在する可能性があることを認識する解決策を検討することをお勧めします。たとえば、CSV に区切り文字が存在します。そのようなツールの1つはミラー、できる場所1
$ mlr -N --csv --fs '~' put '$9 = gsub($9,"~"," ")' INFILE.dat
1235678~2005-04-13-13.49.42.149512~10~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~2000 2001~N~0.00~9999.63~2005-04-13-13.49.42.149556
- Millerの新バージョンではサブシステム(文字列置換)この場合に望ましい関数