ファイルの2番目のフィールドをアンダースコア(スペースで区切って)に分割し、2番目の部分をデータに新しいフィールド(タブとして出力)として追加する方法を簡単にしたいという質問があります。
例えば
file.txt
2 1_123
2 2_345
out.tab
:
2 1_123 123
2 2_345 345
すでに使用できますが、より簡単な方法はありますか?複雑すぎるようです...
paste -d' ' file.txt <(cat file.txt | cut -d'_' -f 2- ) | tr [:blank:] \\t > out.temp && mv out.temp out.tab
答え1
すべての変換はファイル内の同じ行内でデータを混在させるため、sedやawkなどのデータを1行ずつ操作するツールを使用する方がはるかに簡単です。
sed -e 's/^[^ \t]*[ \t][^ \t]*_\([^_ \t]*\)/&\1\t/' -e 'y/ /\t/' <<<'2 1_123'
説明:正規表現を使用して、最初のフィールド(最初のスペースまたはタブまで)、2番目のフィールドから最後のアンダースコアまで、2番目のフィールドを最後のアンダースコア(\(…\)
テキストを置き換えるためにグループに入れます)と一致させます。同じテキスト(&
置換)を保持し、その後に一致するグループの内容(\1
)が続きます。 2番目のフィールド以降のすべてのフィールドは変更されません。最後に、すべてのスペースをタブ文字で置き換えます。
sedがタブ表示をサポートしていない場合は、\t
代わりにリテラルタブを使用してください。
答え2
2番目と最後のフィールドに1つの下線のみを表示する簡単な例を表示するには、次のようにします。
$ sed 's/_\(.*\)/& \1/' file | tr ' ' '\t'
2 1_123 123
2 2_345 345
または、sed
実装が拡張正規表現をサポートしている場合:
$ sed -E 's/_(.*)/& \1/' file | tr ' ' '\t'
2 1_123 123
2 2_345 345
これは最初の項目_
とそれ以降のすべての項目と一致します。角かっこは一致する文字列をキャプチャし、それらを置換の右側に引用することができます\1
。&
一致するすべての項目なので、_
2 番目のフィールドの残りの部分がその後に続きます。したがって、置換はそれ自体、スペース、および次の文字を印刷します_
。tr
すべてのスペースをタブに置き換えます。
必要な数のフィールドを持つことができ、そのうちの1つを含めることができるより複雑な場合は、次のようにし_
ますperl
。
$ perl -lane 's/ +/\t/g; $F[1]=~/_(\S+)/; print "$_\t$1"' file
2 1_123 123
2 2_345 345
-a
これにより、perl
入力スペースが配列に分割されます@F
。 2番目のフィールドは、$F[1]
配列が最初から計算されるためです0
。-n
「入力ファイルを1行ずつ読み、-e
与えられたスクリプトを適用する」という意味です。-l
入力行から末尾の改行を削除し、各呼び出しに改行を追加しますprint
。
s/ +/\t/g;
1つ以上のスペースを含むすべての項目をタブに置き換え、$F[1]=~/_(\S+)/;
2番目のフィールドの次の文字_
と一致して別の名前で保存し、$1
現在print "$_\t$1"
の行($_
)と一致を印刷します。
フィールドデータに基づいたもう1つの便利なツールは次のとおりですawk
。
$ awk '{gsub(/ /,"\t");l=$2; sub(/.*_/,"",l); print $0"\t"l}' file
2 1_123 123
2 2_345 345
では、awk
入力行が空白に自動的に分割され、$1
m $2
...になります$N
。gsub(/ */,"\t");
すべてのスペースをタブに置き換えます。までの内容をすべて削除し、()行を印刷してから、タブと修正された2番目のフィールドをl=$2
印刷します。l
sub(/.*_/,"",l);
_
l
print $0"\t"l
$0
答え3
t=$(printf \\t)
sed "s/[^ _]*\(_\([^ _]*\)\)\{0,1\}[^ ]*/& \2/2;s/ */$t/g" <in >out
...2番目のフィールドの数に関係なく、またはフィールド数に関係なく機能する必要があります。ただし、一連のスペースを単一のタブ文字に変換します。 2つの連続したスペースを2つのフィールド区切り文字と見なす必要がある場合は、次のようにします。
y/ /$t/
...代わりにそこに行きます...
s/ */$t/
...置換。