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

gkm*_*hit 93 shell cut tr

我有一个文件,f1.txt

ID     Name
1      a
2         b
3   g
6            f
Run Code Online (Sandbox Code Playgroud)

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

这是我到目前为止:

cat f1.txt | tr -d " "
Run Code Online (Sandbox Code Playgroud)

但输出是:

IDName
1a
2b
3g
6f
Run Code Online (Sandbox Code Playgroud)

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

ID Name
1 a
2 b
3 g
6 f
Run Code Online (Sandbox Code Playgroud)

请尽量避免sed

cuo*_*glm 134

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

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f
Run Code Online (Sandbox Code Playgroud)

或者您可以使用以下awk解决方案:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f
Run Code Online (Sandbox Code Playgroud)

当您更改 record 中的字段时,awkrebuild $0,将所有字段合并在一起,用 分隔OFS,默认情况下是一个空格。

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

  • 这里有一个小的区别。`tr` 将用一个空格替换一行末尾的两个空格。`awk` 将删除所有尾随空格。 (4认同)

pol*_*lym 29

只需使用column

column -t inputFile
Run Code Online (Sandbox Code Playgroud)

输出:

ID  Name
1   a
2   b
3   g
6   f
Run Code Online (Sandbox Code Playgroud)

  • 然后使用 awk:`column -t file | awk '{print $2}'` 只打印第二列 (4认同)
  • @Unknown 很高兴为您服务:)! (2认同)

use*_*018 12

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

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"
Run Code Online (Sandbox Code Playgroud)

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

在我的情况下,我想将所有空格标准化为一个空格,这样我就可以将该空格作为分隔符。

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

 -s uses the last specified SET, and occurs after translation or deletion.
Run Code Online (Sandbox Code Playgroud)

这使我们能够消除第一个 tr。面对我的密集,工藤要表现出他的耐心。

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

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2
Run Code Online (Sandbox Code Playgroud)

之后,通过挤压指定 SET2:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2
Run Code Online (Sandbox Code Playgroud)

输出:

6379
Run Code Online (Sandbox Code Playgroud)

有关涵盖空格细微差别的更多详细信息

演示当涉及到 [: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
Run Code Online (Sandbox Code Playgroud)

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

  • 所以 ´tr -s "[:blank:]" " "´ 应该这样做,它首先将所有空白转换为空格,然后压缩空格。不需要第二个“tr”。 (2认同)
  • 我尝试了``printf 'ID \t Name\n' | tr -s "[:空白:]" " " | od -cb`` (按照 @dastrobu 的建议),我得到了 ``ID Name\n`` (带有 ***one*** 空格)作为输出。你真的尝试过吗,@user3183018? (2认同)
  • 好吧,让我试着再说一遍。我做了``printf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"`` (按照 @dastrobu 的建议),其中 `␣` 代表一个空格,我得到 `ID␣Name\n` (带有一个空格)作为输出。这与“Port&lt;SPACE&gt;&lt;TAB&gt;&lt;SPACE&gt;6379”的[您的示例](https://unix.stackexchange.com/q/145978/23408#comment782967_289690)完全相同,除了我使用了来自的标题字符串的问题。我想知道您是否尝试过 `tr -s "[:blank:]"` (没有最后的 `"␣"` 参数)。 (2认同)
  • 当我执行 `printf 'ID \t Name\n' | 时 od -cb`,它准确地显示了它应该显示的内容:`I` `D` ``⁠ `` `\t` ``⁠ `` `N` `a` `m` `e` `\n` (即“I”“D”“040”“011”“040”“N”“a”“m”“e”“\n”)。同时,根据你自己的证据,你犯的错误正是我猜测的:你正在运行 `tr -s "[:blank:]"` (即 `tr` 带有一个选项和 *一个* 参数),而不是 @dastrobu 和我现在已经提出四次的命令:``tr -s '[:blank:]' '␣'`` (即,带有一个选项的 `tr` 和 ***两个**论点*)。 (2认同)

Sco*_*ott 6

谁需要程序(shell 除外)?

while read a b
do
    echo "$a $b"
done < f1.txt
Run Code Online (Sandbox Code Playgroud)

如果您希望第二列中的值对齐,如 polym 的column答案,请使用printf代替echo

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt
Run Code Online (Sandbox Code Playgroud)