次のようなテキストファイルがあります。
12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8', '5.112.1.10']
separated by ',',
と言うMySQLコマンドを使用してファイルの内容をテーブルに挿入したいので、角かっこで囲まれたlat文字列(コンマで区切られた文字列を含む場合があります)は、MySQLがそれらを区切りたいが、テーブルにそれらのための十分な列。
角かっこ[]
の間にあるコンマをセミコロン;
に置き換えたい。
Linuxでこれを簡単な方法で行うにはどうすればよいですか?
角括弧内で,
で区切られた文字列の数は定義されていません。 1、2、3などになります。括弧内にある場合は常に,
を;
に置き換える必要があります。
sed
も同様に機能する可能性があります:
sed 'h; s/.*[[]/[/; s/,/;/g; x; s/[[].*//; G; s/\n// ' file
説明:
sed ' h; save the entire line to hold space
s/.*[[]/[/ remove anything till the opening `[`
s/,/;/g replace ALL commas with semicolons
x save modified bracketed text, get back original line
s/[[].*// get rid of the bracketed text
G append the modified text
s/\n// remove the <newline> char introduced by `G`
' file
角かっこ内の文字列には常に一重引用符が付いているため、次のようにペアを置き換えることができます。
_$ sed "s/',/';/g" file
12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4'; '2.3.4.5']
_
長さが3までの括弧内の部分文字列の場合(_['xxx', 'yyy', 'zzz']
_)。 sed
を使用してこれを行うことができます。
_$ sed 's/\([^\[]*\)\([^,]*\),\([^,]*\)/\1\2;\3/g' file
12.com,128.15.8.6,TEXT1,no1;['128.15.8.6']
23com,122.14.10.7,TEXT2,no2;['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3;['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10'; '1.2.3.4']
_
このソリューションには、簡単な検索と置換があります_s/.../.../g
_
s/\([^\[]*\)
-_[
_(ゼロ以上)までのすべてに一致し、_\1
_に保存します\([^,]*\)
-_,
_までのすべてに一致し、_\2
_に保存します,
_-カンマに一致\([^,]*\)
-カンマ以外のすべてに一致し、_\3
_に保存します/\1\2;\3/g
_-ビットを再構築して_\1\2;\3
_になり、これを貪欲に行いますそれが最後のフィールドであり、列の数が固定されている場合は、bashを使用できます。
while IFS=, read v1 v2 v3 v4 rest; do
echo "$v1,$v2,$v3,$v4,${rest//,/;}"
done
結果:
12.com,128.15.8.6,TEXT1,no1,['128.15.8.6']
23com,122.14.10.7,TEXT2,no2,['122.14.10.7']
45.com,91.33.10.4,TEXT3,no3,['91.33.10.4']
67.com,88.22.88.8,TEXT4,no4,['88.22.88.8'; '5.112.1.10']
上記のステートメントをファイルに配置し(上部の#!/bin/bash
と一緒に)、ファイルをstdinとしてそのスクリプトにフィードするか、スクリプトでファイルに名前を付けることができます。
while IFS=, read v1 v2 v3 v4 rest; do
echo "$v1,$v2,$v3,$v4,${rest//,/;}"
done < yourfile
これは、IFS
を使用して、,
で行を分割します。最初の4つのフィールドはv1..v4に割り当てられ、その後のすべては最後の変数(ここではrest
と呼ばれます)に割り当てられます。次に、エコーは,
で区切られた変数を出力しますが、最後の変数では;
に置き換えられます。
ネストされた[...]
がないと仮定します。
sed -e :1 -e 's/\(\[[^]]*\),/\1;/g' -e t1 < file.in > file.out
awkはここでは非常に優れています。フィールド区切り文字として開き角かっこを使用し、2番目のフィールドのすべてのコンマを置き換えます。
awk 'BEGIN {FS = OFS = "["} {gsub(/,/, ";", $2)} 1' file