仅使用 'tr' 将多个空格替换为一个

仅使用 'tr' 将多个空格替换为一个

我有一个文件f1.txt

ID     Name
1      a
2         b
3   g
6            f

空格数为不是固定的。仅使用一个空格替换所有空格的最佳方法是什么tr

这是我到目前为止所拥有的:

cat f1.txt | tr -d " "

但输出是:

IDName
1a
2b
3g
6f

但我希望它看起来像这样:

ID Name
1 a
2 b
3 g
6 f

请尽量避免sed

答案1

tr,使用s挤压重复选项:

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

或者你可以使用一个awk解决方案:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

当您更改记录中的字段时,awk重建$0会获取所有字段并将它们连接在一起,并用 分隔OFS,默认情况下是空格。

这会将空格和制表符序列(以及可能的其他空白字符,具体取决于 的区域设置和实现awk)压缩到一个空格中,同时还会删除每一行的前导和尾随空白。

答案2

只需使用column:

column -t inputFile

输出:

ID  Name
1   a
2   b
3   g
6   f

答案3

如果你想压缩“空白”,你需要使用 tr 的预定义字符集“:blank:”(水平空白制表符和空格)或“:space:”(垂直空白):

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

示例在 Red Hat 5 (GNU tr) 上运行。

就我而言,我想将所有空白标准化为单个空格,这样我就可以依靠空格作为分隔符。

正如 dastrobu 的第二条评论所指出的,我错过了手册页中的措辞:

 -s uses the last specified SET, and occurs after translation or deletion.

这使我们能够消除第一个 tr。面对我的笨拙,工藤实在是太没耐心了。

之前,从 Redis 配置中解析端口。文件:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

之后,通过挤压指定 SET2:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

输出:

6379

有关空白细微差别的更多详细信息

演示当涉及属于 [:blank:] 字符类的连续混合字符时,单独挤压会失败:

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

注意:我的 printf 格式的两个字符串字段由 1 个空格、1 个制表符、1 个空格分隔。挤压后该序列仍然存在。在八进制转储的输出中,这由 ascii 序列 040 011 040 表示。

答案4

这是一个老问题,已经解决过很多次了。只是为了完整性:我有一个类似的问题,但想通过管道将线路传递到另一个程序。我用了参数

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

所以cat f1.txt | xargs -L1似乎输出正是你想要的。

相关内容