并排显示两个文件


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之间打印一个标签

我想出的解决方案使用sdiff,然后通过管道进行sed来删除输出sdiff

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

我可以创建一个函数并将其粘贴在我的函数中,.bashrc但是肯定已经存在一个命令(或者可能存在更干净的解决方案)?


不在外壳中,但值得一提:使用meld
fedorqui'SO stop harm''Sep

Answers:


166

您可以使用标记来合并文件(每列一个),并省略标题(例如)pr来执行此操作。-m-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 2012年

1
pr有办法自动检测屏幕宽度吗?
马特

2
@Matt:可以使用$COLUMNS,它应该由外壳提供。
Hasturkun 2014年

1
当用于并排打印两个文件时,pr剪切长行的结尾。有没有办法让它包住线?
molnarg 2015年

32

为了进一步说明@Hasturkun的答案:默认情况下pr,其输出仅使用72列,但使用终端窗口的所有可用列相对容易:

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

大多数外壳将在环境变量中存储(并更新)终端的屏幕宽度$COLUMNS,因此我们只是将该值传递给pr宽度给其以用于其输出的宽度设置。

这也回答了@Matt的问题:

pr有办法自动检测屏幕宽度吗?

因此,不行:pr本身无法检测到屏幕宽度,但是通过该-w选项传入了终端的宽度,我们对此有所帮助。


7

如果您知道输入文件没有选项卡,则使用可以expand简化@oyss答案

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
从来没有说过,但是如果我想偶尔并排显示两个文件,那么与编写/记住脚本相比,这样做diff -y one.txt two.txtpaste one.txt two.txt删除差异显示的多余字符要好得多。即使两者都用更长的时间!=更好,更易读,更快..在这里有什么优势?sedawk.bash_rc
克里斯·西摩

2

从Barmar的答案中动态删除字段长度计数将使其变得更短....但是您仍然需要至少一个脚本来完成工作,无论您选择哪种方法都无法避免。

paste one.txt two.txt |awk -F'\t' '{printf("%-50s %s\n",$1,$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
苹果
梨
比最后两个更长的线
最后一行
[root /]# cat /two.txt
快棕色狐狸..
富
酒吧
linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
苹果| 快棕色狐狸..
梨| 富
比最后两个更长的线| 酒吧
最后一行 linux

sdiffdiff -y我在问题中讨论的。
克里斯·西摩

是的,没错……有人提到它是用来显示执行此操作的另一个命令/标志设置。
iAdhyan 2014年

但这并不能回答diff在两个文件之间添加字符的问题。
克里斯·西摩

我感到很害怕,您是以root身份执行此操作的
Pryftan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.