2つのファイルを並べて表示する


94

長さの異なる2つのソートされていないテキストファイルを(列で)並べて表示する方法shell

考えるone.txttwo.txt

$ cat one.txt
apple
pear
longer line than the last two
last line

$ cat two.txt
The quick brown fox..
foo
bar 
linux

skipped a line

表示:

apple                               The quick brown fox..
pear                                foo
longer line than the last two       bar 
last line                           linux

                                    skipped a line

paste one.txt two.txtほぼトリックを実行しますが、列1と2の間に1つのタブを印刷するだけなので、列を適切に配置しません。emacsとvimを使用してこれを行う方法は知っていますが、出力を標準出力に表示してパイピングなどに使用します。

私が思いついた解決策はsdiff、sedへのパイプを使用して出力を削除しsdiffます。

sdiff one.txt two.txt | sed -r 's/[<>|]//;s/(\t){3}//'

私は関数を作成してそれに貼り付けることができます.bashrcが、確かにこれに対するコマンドはすでに存在しています(または潜在的によりクリーンなソリューション)?


シェルではありませんが、言及する価値があります:meldを使用しください!
fedorqui 'SO stop harming' 2016

回答:


166

あなたは使用することができますpr使用して、これを行うには-m、ファイル、列ごとに1、およびマージするフラグを-t省略ヘッダに、例えば。

pr -m -t one.txt two.txt

出力:

apple                               The quick brown fox..
pear                                foo
longer line than the last two       bar
last line                           linux

                                    skipped a line

関連項目:


15
パーフェクト!これまで聞いたことがない、何かが存在することを知っていましたpr。3つのファイルを試してみましたが、出力は切り捨てられましたが、-wオプションで解決しました。素敵な答え。
クリスシーモア

5
@sudo_o:喜んでお手伝いします、coreutilsは宝石でいっぱいです
Hasturkun

1
prが画面幅を自動検出する方法はありますか?
マット14

2
@マット:$COLUMNSシェルで提供されるを使用できます。
Hasturkun 2014

1
2つのファイルを並べて印刷するときに使用するとpr、長い行の終わりがカットされます。行を折り返す方法はありますか?
molnarg 2015

32

@Hasturkunの答えを少し拡張するには:デフォルトでprは出力に72列のみを使用しますが、ターミナルウィンドウの使用可能なすべての列を使用することは比較的簡単です。

pr -w $COLUMNS -m -t one.txt two.txt

ほとんどのシェルは、端末の画面幅を環境変数に格納(および更新)するため、出力の幅設定に使用するために、その$COLUMNS値を渡すだけですpr

これは@Mattの質問にも回答します。

prが画面幅を自動検出する方法はありますか?

したがって、いいえ:prそれ自体は画面幅を検出できませんが、-wオプションを介して端末の幅を渡すことで少し助けます。


7

入力ファイルにタブがないことがわかっている場合は、を使用すると@oyss回答がexpand簡素化されます

paste one.txt two.txt | expand --tabs=50

入力ファイルにタブがある場合は、常に最初に展開できます。

paste <(expand one.txt) <(expand two.txt) | expand --tabs=50

6
paste one.txt two.txt | awk -F'\t' '{
    if (length($1)>max1) {max1=length($1)};
    col1[NR] = $1; col2[NR] = $2 }
    END {for (i = 1; i<=NR; i++) {printf ("%-*s     %s\n", max1, col1[i], col2[i])}
}'

使用する*フォーマット仕様にすることで、動的にフィールドの長さを供給することができます。


1
言ったことはありませんが、2つのファイルを時々並べて表示したい場合は、表示される余分な文字をdiffで削除するdiff -y one.txt two.txtよりも作業が簡単で、スクリプトの作成や記憶に比べれば簡単です。両方の関数としてより長く!=より良く、より読みやすく、より速く..ここの利点は何ですか?paste one.txt two.txtsedawk.bash_rc
クリスシーモア

2

Barmarの回答からフィールド長のカウントを動的に削除すると、コマンドがはるかに短くなります。ただし、どの方法を選択しても回避できなかった作業を完了するには、少なくとも1つのスクリプトが必要です。

paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$2)}'

2

2つのファイルの実際の違いを並べて知りたい場合は、次を使用しますdiff -y

diff -y file1.cf file2.cf

-W, --width=NUMオプションを使用して出力幅を設定することもできます。

diff -y -W 150 file1.cf file2.cf

およびdiffの列出力を現在のターミナルウィンドウに合わせるには:

diff -y -W $COLUMNS file1.cf file2.cf

2

sed方法があります:

f1width=$(wc -L <one.txt)
f1blank="$(printf "%${f1width}s" "")"
paste one.txt two.txt |
    sed "
        s/^\(.*\)\t/\1$f1blank\t/;
        s/^\(.\{$f1width\}\) *\t/\1 /;
    "

、あなたは使うことができますprintf -v

f1width=$(wc -L <one.txt)
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
    sed "s/^\(.*\)\t/\1$f1blank\t/;
         s/^\(.\{$f1width\}\) *\t/\1 /;"

(もちろん、@ Hasturkunのソリューションpr最も正確です!)

sed以上の利点pr

分離幅やセパレータを細かく選択できます。

f1width=$(wc -L <one.txt)
(( f1width += 4 ))         # Adding 4 spaces
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
    sed "s/^\(.*\)\t/\1$f1blank\t/;
         s/^\(.\{$f1width\}\) *\t/\1 /;"

または、サンプルとして、次を含む行をマークしますline

f1width=$(wc -L <one.txt)
printf -v f1blank "%${f1width}s"
paste one.txt two.txt |
    sed "s/^\(.*\)\t/\1$f1blank\t/;
  /line/{s/^\(.\{$f1width\}\) *\t/\1 |ln| /;ba};
         s/^\(.\{$f1width\}\) *\t/\1 |  | /;:a"

レンダリングされます:

apple                         |  | The quick brown fox..
pear                          |  | foo
longer line than the last two |ln| bar 
last line                     |ln| linux
                              |  | 
                              |ln| skipped a line

1

以下のpythonベースのソリューションを見つけてください。

import sys

# Specify the number of spaces between the columns
S = 4

# Read the first file
l0 = open( sys.argv[1] ).read().split('\n')

# Read the second file
l1 = open( sys.argv[2] ).read().split('\n')

# Find the length of the longest line of the first file
n = len(max(l0, key=len))

# Print the lines
for i in  xrange( max( len(l0), len(l1) ) ):

    try:
        print l0[i] + ' '*( n - len(l0[i]) + S) + l1[i]
    except:
        try:
            print ' ' + ' '*( n - 1 + S) + l1[i]
        except:
            print l0[i]

apple                            The quick brown fox..
pear                             foo
longer line than the last two    bar 
last line                        linux

                                 skipped a line

0
diff -y <file1> <file2>


[root /]# cat /one.txt
林檎
梨
最後の2つより長いライン
最終行
[root /]# cat /two.txt
クイックブラウンフォックス
foo
バー
Linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
りんご| クイックブラウンフォックス
梨| foo
最後の2つより長い行| バー
最後の行| Linux

sdiffdiff -y、私は問題の議論います。
Chris Seymour

はい、そうです...それを行う別のコマンド/フラグ設定を示すことが言及されました。
iAdhyan

ただしdiff、2つのファイルの間に文字を追加する質問には答えません。
Chris Seymour 14年

あなたは...ルートとしてこれをやっている、それが怖い私を見つける
Pryftan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.