sed 将所有制表符和空格替换为单个空格

sed 将所有制表符和空格替换为单个空格

我得到了如下字符串:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

现在我想用一个空格替换记录之间的所有制表符/空格,这样我就可以轻松地使用它cut -d " "

我尝试了以下操作:

sed "s/[\t[:space:]]+/[:space:]/g"

以及各种变体,但无法使其工作。有什么想法吗?

答案1

使用sed -e "s/[[:space:]]\+/ /g"

以下是解释:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

对于替换,您只需插入一个空格。[:space:]在那里不起作用,因为那是字符类的缩写,而正则表达式引擎不知道在那里放什么字符。

必须+在正则表达式中转义,因为在 sed 的正则表达式引擎中,+是普通字符,而\+是“一个或多个”的元字符。在掌握正则表达式Jeffrey Friedl 在脚注中提到,ed 和 grep 使用转义括号,因为“Ken Thompson 认为正则表达式主要用于处理 C 代码,其中匹配原始括号比反向引用更常见。”我认为他对加号也有同样的感受,因此需要将其转义以将其用作元字符。很容易被这一点绊倒。

在 sed 中,你需要转义+, ?, |,(). 或者使用 -r 来使用扩展正则表达式(然后它看起来像sed -r -e "s/[[:space:]]\+/ /g"sed -re "s/[[:space:]]\+/ /g"

答案2

您可以使用-s以下(“挤压”)选项tr

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

字符[:blank:]类包括空格和制表符。

答案3

下面是我通过实验发现的一些有趣的方法(使用 xxd 查看标签)。

echo -e \\033c
s=$(echo -e "a\t\tb\t\tc\t\td\t\te\tf")

echo 'original string with tabs:'
echo "$s"
echo "$s" | xxd

echo -e '\nusing: \techo "$s" | tr -s \\\\t " "'
echo "$s" | tr -s \\t " "
echo "$s" | tr -s \\t " " | xxd

echo -e '\nusing: \techo "$s" | sed '"'s/\\\\t/ /g'"
echo "$s" | sed 's/\t\+/ /g'
echo "$s" | sed 's/\t\+/ /g' | xxd

echo -e '\nusing: \techo ${s/ / }'
echo ${s/ / }
echo ${s/ / } | xxd

z=$(echo $s)
echo -e '\nusing: \tz=$(echo $s); echo "$z"'
echo "$z"
echo "$z" | xxd

echo -e '\nusing: \tread s < file.in; echo $s'
read s < file.in
echo $s
echo $s | xxd

echo -e '\nusing: \twhile read s; do echo $s; done'
while read s;
do
  echo $s
done < file.in

答案4

我喜欢使用以下 bash 别名。基于其他人写的内容,使用 sed 搜索并将多个空格替换为单个空格。这有助于从 cut 获得一致的结果。最后,我再次通过 sed 运行它以将空格更改为制表符,以便更易于阅读。

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'

相关内容