哪些命令将输入​​制表符分隔的文本文件,并将每行削减为80个字符?


8

我有(有时)制表符分隔的数据的多行文本文件。我想输出文件,以便我可以浏览它-所以我只希望看到每行的前80个字符(我设计了文本文件,将重要内容放在每行的第一位)。

我以为我可以用cat读取文件的每一行,并将每一行发送到管道中的下一个命令:

cat tabfile | cut -c -80

但这似乎是坏事。我试着胡闹,grep似乎可以工作-但后来我发现,不行(不是文件中的每一行都包含80多个字符)-看来,制表符被切为单个字符。

我试过了:

cat tabfile | tr \t \040 | cut -c -80

通过消除空白可读性,即使那样会使我的数据有些混乱。但这没有用。都没有:

cat tabfile | tr \011 \040 | cut -c -80

也许我使用的tr错误?我以前在tr上遇到过麻烦,想删除多个空格(似乎我在这台机器上可以访问的tr的版本有一个-s选项,用于压缩多个字符-我可能需要更多地使用它)

我确定如果弄乱了我可以使用perl,awk或sed或其他方法来执行此操作。

但是,我想要一个使用(POSIX?)常规命令的解决方案,以使其尽可能地可移植。如果最终使用tr,则可能最终会尝试将制表符转换为字符,也许要进行计算,削减计算量,然后将这些字符转换回制表符以进行输出。

它不必是一行,也不需要直接在命令行中输入-脚本就可以了。


关于选项卡文件的更多信息:

我使用制表符来中断字段,因为有一天我可能想将数据导入其他程序。所以我倾向于在内容之间只有一个选项卡。但是我也使用制表符将内容与垂直列对齐,以帮助查看纯文本文件时提高可读性。这意味着对于某些文本,我会在内容的末尾用空格填充,直到到达选项卡将使下一个字段与上下两个字段对齐的位置为止。

DarkTurquoise#00CED1海洋,天空,划艇自然
MediumSpringGreen#00FA9A对树魔术有用  
青柠#00FF00仅用于春鸡和果肉

因此,您想要80个字符来计数制表符宽度吗?您可以用适当数量的空格替换制表符,然后使用cut。
穆鲁

Annnnnd,我如何(轻松)将单个字符扩展为多个字符?或者,更重要的是,使用可变数量的字符(取决于行中其他字符的数量),因为我使用标签将每个标签之前/之后的信息量垂直排列起来。就像我说的,如果我想学习perl / awk / sed,我可以,但是我想要简单的东西
user3082 2014年

你可以尝试prcoreutilspr -1 -t -l200 -W80 file。根据需要增加/减少页面长度(处的数字-l)。
don_crissti 2014年

唐,您的建议(为什么不是答案?)给了我一个很好的错误消息。但是人说“公关-打印文件”,所以调查一下。
user3082 2014年

唐,将其作为答案,让我们在此处进行讨论。我有一些看起来很像您的东西-大部分相同的格式,大部分都相同的标志:-w而不是-W等...
user3082 2014年

Answers:


9

我认为您正在寻找expand和/或unexpand。看来您正在尝试确保\tAb宽度算作8个字符,而不是单个字符。fold也会执行此操作,但是它将输入内容包装到下一行而不是将其截断。我想你要:

expand < input | cut -c -80

expand并且unexpand指定POSIX

  • expand工具将写入文件或标准输入与标准输出\tAB人物与一个或多个替代空间需要垫下一个制表位字符。任何退格字符都应复制到输出,并导致用于制表位停止计算的列位置计数减少;列位置计数不应减少到零以下。

很简单 因此,下面是它的作用:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

until顶部的循环获取一组数据,例如...

1 1 2 2 3 3 ...

printf是用%*sarg填充标志来实现的,因此对于集合中的每个填充printf符,都将填充与参数个数一样多的空格。在每个\t字符后面附加一个ab字符。

所有tees用于显示每个滤镜在应用时的效果。

结果是:

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

这些行按两组排列,例如...

  1. 输出 printf ...; echo
  2. tr ...或的输出expand
  3. 输出 cut
  4. 输出 wc

前四行是tr过滤器的结果-其中每个\tab都转换为一个空格

以及排名倒数第四的结果expand链。


1
其实,不在乎(太多),如果\ t被算作8(5?)或一个,只是它没有算作一个显示为8
user3082

+ @ anon3202-非常合理。我理解您的意思- (顺便说一下,制表位长度是cli选项) -我只是没有尽我所能说。希望您能掌握要点-正如我所认为的那样。
mikeserv 2014年

我没有完全按照解释进行操作,但是随便展开扩展显示,扩展绝对是我想要的。
user3082 2014年

3

由于制表符更多是为了对齐而不是定界,因此一种方法可能是使用column,然后使用cut

column -s '\t' -t <some-file | cut -c -80

看来column不是POSIX。它是Ubuntu上BSD utils的一部分,因此我认为它是跨平台的。


使用column这种方式,OP甚至不需要手动添加空格来对齐。
贝尼·切尔尼亚夫斯基-帕斯金,2013年

1

Don在评论中的建议是一个好的开始。

这是我使其(主要)工作所需的:

pr +1 -1 -t -m -l1000 -w 80 tabfile

-m需要,使-w单个列上的标志生效。手册页可以使用一些重写来表明这一点。

尝试解决方法时,我发现pr输出\t字符,因此将其输入结果会cut导致相同的问题。

-1 (列标志)在手册页中专门说:

此选项不应与-m一起使用。

但是,如果没有此选项pr,则会以比指定长度短得多的方式截断行。

pr还会在字段中的每个单词之前(或之后?)插入一个空格(即,每个我有一个空格的地方,在处理后都有两个空格)。如果单词过多,插入的空格将忽略该-w限制(创建环绕)。但是,奇怪的是,否则用非制表符分隔(即用空格隔开)的“列”仍然排成一行。



0

一个应该真正了解显示宽度的实用程序是fold:不幸的是,它似乎没有选择放弃而不是包装。尽管它可能效率极低,但是您可以执行以下操作

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
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.