2012-04-03 14 views
4

は私が道 FILE1以下の形式のファイルを変更する方法についてのアドバイスを必要とするファイルの形式に変更するワンライナーをawkは:のPerl、sedは、または

A  B 
504688 jobnameA 
504690 jobnameB 
504691 jobnameC 
... 
:FILE2に

A  504688 
B  jobnameA 
A  504690 
B  jobnameB 
A  504691 
B  jobnameC 
... 

を私は考えることができ

一つの解決策は次のとおりです。

cat file1 | perl -0777 -p -e 's/\s+B/\t/' | awk '{print $2"\t"$3}'. 

しかし、もっと効率的な方法や、すでに知っているがある場合、私は疑問に思ってこの仕事をする練習。

+2

はあなたに非常に多くのマットに感謝します。私は最近コミュニティに参加しました。私はそれをします – Alby

答えて

7
perl -nawe 'print "@F[1 .. $#F]", $F[0] eq "A" ? "\t" : "\n"' < /tmp/ab 

perlrunのオプションを検索します。

追加するもう1つの有用なものは-lです(この場合は改行を追加してください)。ここで

+0

非常にいいです。 @Fを使用するライナーは私の本では涼しいです:) –

+0

@briandfoy - ありがとう - それは本当に単なるライナーです。そして、私が[あなたの本](http://amzn.com/0321496949)を読んだことを安心してください! :)と私は非常にそれをお勧めすることができます! – Lumi

+0

ありがとうございました! Btw、本当に必要な最後に向かって "<"ですか?私はそれなしでそれを試して、それはまだ動作します。それは何をするためのものか?出力を指示するのに慣れているだけです。 – Alby

2
awk '/^A/{num=$2}/^B/{print num,$2}' file 

または、交互に、

awk '{num=$2;getline;print num,$2}' file 
1

はsedのソリューションです:

sed -e 'N' -e 's/A\s*\(.*\)\nB\s*\(.*\)/\1\t\2/' file 

このバージョンはまた、上部のヘッダを出力します:

sed '1{h;s/.*/A\tB/p;g};N;s/A\s*\(.*\)\nB\s*\(.*\)/\1\t\2/' file 

または代替:

sed -n '/^A\s*/{s///;h};/^B\s*/{s///;H;g;s/\n/\t/p}' file 

あなたのsedがない場合代替のコマンドセパレータとしてセミコロンをサポートしない:

sed -n ' 
/^A\s*/{  # if the line starts with "A" 
s///    # remove the "A" and the whitespace 
h    # copy the remainder into the hold space 
}    # end if 
/^B\s*/{  # if the line starts with "B" 
s///    # remove the "B" and the whitespace 
H    # append pattern space to hold space 
g    # copy hold space to pattern space 
s/\n/\t/p  # replace newline with tab and print 
}' file 

このバージョンはまた、上部にヘッダを印刷する:

sed -n '/^A\s*/{s///;h;1s/.*/A\tB/p};/^B\s*/{s///;H;g;s/\n/\t/p}' file 
1

これは単に固定されていない、任意のヘッダテキストで動作するB >>

awk '{a=$1;b=$2;getline;if(c!=1){print a,$1;c=1};print b,$2}' file1 >file2 

...それも印刷されますヘッダー行

あなたが\t区切りが必要な場合は、使用します。

awk '{a=$1;b=$2;getline;if(c!=1){print a"\t"$1;c=1};print b"\t"$2}' file1 >file2 
5

入力ファイルを仮定はタブ区切りです:これが何を書かれていたまさにcutpasteあるので

echo $'A\tB' 
cut -f2 filename | paste - - 

はかなり速さが必要となります。

+0

+1 - 'paste'と' join'は永遠の精神的ツールセットに本当にそれを作ったことはありませんが、おそらく最も機械効率の良い解決策です。スペース区切りファイルのバリエーション: 'cut -b8-/tmp/ab | paste - -' – Lumi

+0

うわー...これはとてもエレガントです。ペーストコマンドに何があるのか​​を正確に説明できますか? cygwinのマニュアルページは明示的ではないようです。また、柔軟性もありますか?つまり、下の2行をペースト(転置)するなどのオプションを追加できますか? – Alby

+1

http://man.cx/pasteを参照 - 'paste'は引数としてファイル名をとり、対応する行を結合します。 " - "がファイル名として与えられている場合、そのファイルの行はstdinから読み込まれます。そのコマンドに2つのダッシュがあるので、すべての入力が消費されるまで、1行は「ファイル1」に読み込まれ、もう1行は「ファイル2」に読み込まれます。 –

0

これはあなたのために働くかもしれない:

sed -e '1i\A\tB' -e 'N;s/A\s*\(\S*\).*\nB\s*\(\S*\).*/\1\t\2/' file 
関連する問題