我得到了如下字符串:
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"'