web-dev-qa-db-ja.com

NFとforループを使用してスクリプトを最適化する方法

複数のファイルがあり、それぞれに異なる列数があります。それらを変換してデータベースに挿入したい

たとえば、ファイルtest01:

0001    000000000000001 john smith  45  500
0002    000000000000002 peter jackson   20  80
0003    000000000000002 robert brown    35  100
0004    000000000000007 sarah white 40  300

私の望ましい出力は:

('0001','000000000000001','john smith','45','500'),
('0002','000000000000002','peter jackson','20','80'),
('0003','000000000000002','robert brown','35','100'),
('0004','000000000000007','sarah white','40','300');

これを実現するには、次のスクリプトを使用します。

cat test01 |awk -F'\t' '{print "('\''"$1"'\'','\''"$2"'\'','\''"$3"'\'','\''"$4"'\'','\''"$5"'\''),"}' |sed '$ s/.$/;/' 

そして、それは正常に機能します。問題は、列数が異なる別のファイルを見つけた場合です。そのため、スクリプトを手動で変更する必要があります。

AWKの変数NFで列の数を取得できることはわかっていますが、この変数をスクリプトのforループと組み合わせる方法は?

私がしようとすると

cat test01 | awk '{for (i = 1; i <= NF; i++){print $i"'\'','\''"}}'

私はこの結果を得ます:

0001','
000000000000001','
john','
smith','
45','
500','
0002','
000000000000002','
peter','
jackson','
20','
80','
0003','
000000000000002','
robert','
brown','
35','
100','
0004','
000000000000007','
sarah','
white','
40','
300','
4

GNU sedを使用:

$ sed -e "s/^/('/" -e "s/\t/','/g" -e "s/$/'),/" -e '$s/.$/;/' file
('0001','000000000000001','john smith','45','500'),
('0002','000000000000002','peter jackson','20','80'),
('0003','000000000000002','robert brown','35','100'),
('0004','000000000000007','sarah white','40','300');

sedスクリプトは4つの部分に分かれています。

  1. s/^/('/は、行の先頭を('に置き換えます。
  2. s/\t/','/gは、タブを','に置き換えます。これは、GNU sedを必要とするビットです。他のsedの実装では、\tの代わりにリテラルタブを挿入します。
  3. s/$/'),/は、行末を'),に置き換えます。
  4. $s/.$/;/は、最後の行の終わりにあるコンマ(のみ)を;に置き換えます。
4
Kusalananda

入力ファイルがタブで区切られている場合は、以下を試すことができます。

awk -F"\t" -vq="'" -vOFS="','" '$1=$1 {print "(" q $0 q ");"}' filename

または、print関数に引用符を埋め込みます。

awk -F"\t" -vOFS="','" '$1=$1 {print "(" "\x27" $0 "\x27" ");"}' filename
5

最初のスクリプトで希望どおりの動作を実現するには、awkの「printf」メソッドを使用できます。 「印刷」によって置かれた改行を取り除くことを可能にします。私は推測していますが、スクリプトは次のように書き直す必要があります。

cat test01 | awk '{for (i = 1; i <= NF; i++){printf $i"'\'','\''"}; printf "\n";}'
0