并排显示两个文件

两个不同长度的未排序文本文件如何在 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

Display:

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之间打印一个选项卡。我知道如何与 emacs 和 vim,但要输出显示为标准输出管道等。

我想出的解决方案使用 sdiff,然后通过管道 sed 删除输出 sdiff添加。

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

I could create a function and stick it in my .bashrc but surely a command for this exists already (or a 清洁工 solution potentially)?

83717 次浏览
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])}
}'

在格式规范中使用 *允许动态提供字段长度。

从 Barmar 的答案中移除动态字段长度计数将使它成为一个更短的命令... ... 但是你仍然需要至少一个脚本来完成这项工作,无论你选择什么方法都无法避免。

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

您可以使用 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

参见:

有一种 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 /;
"

Under , you could use 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 /;"

(Of course @Hasturkun 's solution pr is the 非常准确!):

sed优于 pr

You can finely choose separation width and or separators:

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
diff -y <file1> <file2>




[root /]# cat /one.txt
apple
pear
longer line than the last two
last line
[root /]# cat /two.txt
The quick brown fox..
foo
bar
linux
[root@RHEL6-64 /]# diff -y one.txt two.txt
apple                                                         | The quick brown fox..
pear                                                          | foo
longer line than the last two                                 | bar
last line                                                     | linux

对于 @ Hasturkun的答案稍作扩展: 在默认情况下,pr只使用72列作为输出,但是使用终端窗口的所有可用列相对容易:

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

大多数 shell 都会在 $COLUMNS shell 变量中存储 (及更新)终端的屏幕宽度,所以我们只是将这个值传递给 pr来设置其输出的宽度。

这也回答了 @ Matt的问题:

有没有一种方法,公关自动检测屏幕宽度?

所以,不: pr本身不能检测到屏幕宽度,但是我们通过它的 -w选项传递终端的宽度来帮助它。

请注意,$COLUMNS是一个 shell 变量,而不是一个环境变量,所以它不会导出到子进程,因此上面的方法可能不会在脚本中工作,只能在交互式 tTYs 中工作..。

If you want to know the actual difference between two files side by side, use diff -y:

diff -y file1.cf file2.cf

You can also set an output width using the -W, --width=NUM option:

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

并使 diff的列输出适合您当前的终端窗口:

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

If you know the input files have no tabs, then using expand simplifies @ oyss's answer:

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

如果输入文件中有选项卡,你可以先展开:

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

下面是一个基于 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