次のようなデータを含むファイルがあります。
a 1
b 2
c,d,e 3,4,5
f 6
g,h 7,8
...そして私は次のような出力が必要です:
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
Pythonを使用してこれを行うことはできますが、シェルスクリプトを使用してこれを試したいと思います。最初に区切り文字「」を含む行を分離してから、先に進むことを考えていました。これまで、これを使用して行を分離しました。
Perl -F, -ane 'print if $#F >=1' filename
...しかし、私は次のステップで立ち往生しています。
Perl
を使用
$ Perl -lane '@v=split/,/,$F[1]; $i=0;
print "$_ $v[$i++]" for split/,/,$F[0]' ip.txt
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
1番目と2番目の列のいずれかを分割し、インデックスカウンターを初期化してから、他の列の分割を繰り返してペアを出力します。
-a
オプションは、入力行を空白で自動分割し、結果を@F
配列
Sedエディターを使用してそれを行う1つの方法は次のとおりです。
sed -e '
s/,/\n/
s/\(\n.*[[:blank:]]\)\([^,]*\),/ \2\1/
P;D
' input.file
作業中:
Perlを使用する別の方法は次のとおりです。
Perl -lane '
my($kref, $vref, %h) = map { [split /,/] } @F[0,1];
@h{@$kref} = @$vref;
print "$_ $h{$_}" for @$kref;
' input.file
別の方法をここに示します。
Perl -lpe 'print "$1 $3" while s/^([^,]*),(.*\h)([^,]*),/$2/' input.file
作業中:
Perl -lane '
my($kref, $vref) = map { [split /,/] } @F;
print shift @$kref, " ", shift @$vref while @$kref && @$vref;
' input.file
作業中:
出力:
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
Awk
ソリューション(その数の「キー」(最初のフィールドに含まれていると仮定)$1
)は常に「値」の数に対応します(2番目のフィールドに含まれます$2
)):
awk '$1 ~ /,/{
len = split($1, keys, ",");
split($2, vals, ",");
for (i = 1; i <= len; i++) print keys[i], vals[i];
next
}1' file
出力:
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
「シェルスクリプトを使用する」-これはbashです:
while read -r key value; do
IFS=, read -ra keys <<<"$key"
IFS=, read -ra vals <<<"$value"
for ((i=0; i < ${#keys[@]}; i++)); do
echo "${keys[i]} ${vals[i]}"
done
done <<END
a 1
b 2
c,d,e 3,4,5
f 6
g,h 7,8
END
Awkの使用:
awk '{gsub(","," "); for(i=0;i<NF/2;i++) print $(i+1),$(i+1+NF/2)}' file
各行からコンマを削除した後、スクリプトは各行のパラメーターの半分をループして、最初のフィールドを行の後半のフィールドと一緒に出力します。
難読化してすみません...
Perl -pe '1 while s/(.*),(.*\h)(.*),/$1 $3\n$2/' infile
各置換は最後のペアを抽出します:
a,b,c 1,2,3 → a,b 1,2 → a 1
c 3 b 2
c 3
ここにはたくさんの解決策がありますprogrammed Perl、awk、sed、bashなどですが、script-solutionはありません。
# /bin/bash
f="yourFile"
paste -d' ' <(cut -d' ' -f1 "$f" | tr , '\n') <(cut -d' ' -f2 "$f" | tr , '\n')
または別の書き方
# /bin/bash
f() { cut -d' ' -f"$1" yourFile | tr , '\n'; }
paste -d' ' <(f 1) <(f 2)
Gnu sed
sed -E ':A;s/([^,]*),([^ ]*) ([^,]*),(.*)/\1 \3\n\2 \4/;tA' infile