私は次のような状況にあります。
my data
:
ID01 120120101
ID02 101010101
ID03 210210210
ID04 505052120
私が望むデータは次のとおりです。output
ID01 1 2 0 1 2 0 1 0 1
ID02 1 0 1 0 1 0 1 0 1
ID03 2 1 0 2 1 0 2 1 0
ID04 5 0 5 0 5 2 1 2 0
だから私は2番目の列に現れるすべての数字を分離したいと思います(私のデータ)、しかし最初の列はそのままにしておく必要があります。
そのために2つのファイルを作成してみました。 1つはID($ 1-file1)、もう1つはスペースで区切られたシーケンス(file2)です。試した後:
sed -i -- 's//\t/g' file2
ただし、次のエラーが発生します。
sed: -e expression #1, char 0: no previous regular expression
この問題をどのように解決できますか?
答え1
どうですか?
perl -alne 'print join " ", $F[0], split("", $F[1])' data
ID01 1 2 0 1 2 0 1 0 1
ID02 1 0 1 0 1 0 1 0 1
ID03 2 1 0 2 1 0 2 1 0
ID04 5 0 5 0 5 2 1 2 0
(完全に)タブ区切りの出力が必要な場合は、次のように変更します。
perl -alne 'print join "\t", $F[0], split("", $F[1])' data
または、ID
2番目のフィールドの数字の後にタブを保持しますが、スペースで区切るには、
perl -alne 'print join "\t", $F[0], join " ", split("", $F[1])' data
答え2
のsed
空の正規表現は、以前の正規表現を再利用することを意味します。この場合、以前の正規表現はありません。列を分離すると、次のことができます。
sed 's/./& /g' file2
(任意の文字を一致させてから、一致する文字に戻して&
スペースを追加してください。)
しかし、2番目の列だけを変更する方が簡単ですawk
。
awk '{gsub(/./, "& ", $2)} 1' data
gsub
sedとほぼ同じですs///g
。私がテストした限り、空の正規awk
表現は実際にはサポートされていますが、最初の数字より前にも一致するので、余分なスペースが追加されます。 (まあ、上記は最後にスペースを追加します。)
答え3
きれいではありませんが、うまくいきます
cat my_data | sed -e 's/./ &/g' -e 's/^ \(.\) \(.\) \(.\) \(.\) /\1\2\3\4/'
最初の表現は、すべての文字の前にスペースを入れます。次に、最初の部分のスペースを削除します。
スクリプトを書くこともできます。
#! /bin/bash
while read ID NUMBERS; do
echo $ID$(echo $NUMBERS | sed -e 's/./ &/g')
done
その後実行
cat my_data | ./my_script
答え4
s
フラグでコマンドを使用できない場合、1つの方法は、そのコマンドと一緒にループ内でそれを使用することですg
(後続の条件によるジャンプ条件)。s
t
s
ここで:
sed -e :1 -e 's/\([^ ]\)\([^ ]\{1,\}\)$/\1 \2/;t1'
つまり、行末の空白でないものを対応する空白、空白、および空白ではないシーケンスに置き換え、その後に空白ではなく1つ以上のシーケンスが続く次の置換がなくなるまで繰り返します。可能です。したがって、各行は次のようになります(最初の行は次のようになります)。
ID01 120120101
-> ID01 1 20120101
-> ID01 1 2 0120101
-> ID01 1 2 0 120101
-> ID01 1 2 0 1 20101
-> ID01 1 2 0 1 2 0101
-> ID01 1 2 0 1 2 0 101
-> ID01 1 2 0 1 2 0 1 01
-> ID01 1 2 0 1 2 0 1 0 1
at this point the "s" command fails, so "t1" doesn't branch
そしてperl
:
perl -pe 's/\S+$/join " ", split "", $&/e'