roff
使用其他“老式”工具(例如许多 Unix 系统上的手册页)创建的文件在简约终端中生成粗体和下划线文本,使用涉及不可打印 ASCII 字符(如“半退格”)的技巧^H
来获取粗体和下划线文本,例如:
b^Hbo^Hol^Hld^Hd and _^Hu_^Hn_^Hd_^He_^Hr_^Hl_^Hi_^Hn_^He_^Hd
如果我希望将其转换为人类可读的纯文本bold and underline
(忽略格式),我可以vim
使用类似:%s:\(.\)\b\1:\1:ge | %s:_\b\(.\):\1:ge
.
我还可以通过管道传输文本tr -dc
并使用 Perl 的一些正则表达式魔法来查找完全由重复字符对构建的单词。
sed
然而,这看起来像是 plain应该能够处理的 事情,这将使在脚本中使用它更加干净。
问题:这个翻译可以吗仅有的使用 POSIX
sed
,即不使用 GNU 或 BSD 扩展?
这里给我带来麻烦的只是不可打印的字符^H
(ASCII #8)。 Bruce Barnett 的书中提到了一个技巧Sed - 简介,但不知何故我无法让它工作。
答案1
你能做这个吗仅有的使用 POSIX sed
?是的:
sed -e 's/.^H//g' < data
其中^H
只是一个字面退格字符。 POSIXsed
使用POSIX 基本正则表达式,它们是通过字节定义的 - 是否打印字符,它们并不关心,因此其行为与^H
字母相同。这里不涉及扩展。请注意,您真正想要做的就是删除退格的字符,因此示例中的捕获组并不是真正必要的。
在大多数情况下,您可以使用 键入退格字符Ctrl+V Ctrl+H。
我认为你潜在的问题是“我如何在 shell 脚本中做到这一点?”,其中字面的退格字符可能会令人不愉快(尽管vim
会很乐意接受同样的Ctrl+V Ctrl+H写法)。这是您链接的介绍的用途tr
。
POSIXtr
支持各种各样的转义字符\b
,包括退格字符的符号转义。您可以将退格字符保存到变量中,并将该变量替换为sed
上面的表达式:
BACKSPACE=$(echo x | tr 'x' '\b')
sed -e "s/.$BACKSPACE//g" < data
我们只是告诉用退格字符tr
替换 an ,并给它一个 single作为输入。这在我可以访问的每个系统上都运行良好,包括 Solaris。然而,x
x
printf
也是 POSIX 定义的工具,并且它支持相同的转义:
BACKSPACE=$(printf '\b')
sed -e "s/.$BACKSPACE//g" < data
这比tr
版本更简单、更直接。请注意表达式周围的双引号sed
,以便我们不再抑制变量插值。你也可以使用命令替换printf '\b'
如果您只想使用一次,而不是使用变量,则可以使用 inline 直接将其放入。
我们可以检查这是否适用于hexdump
(或hd
):
$ dash
$ hexdump -C data
00000000 62 08 62 6f 08 6f 6c 08 6c 64 08 64 0a |b.bo.ol.ld.d.|
$ BACKSPACE=$(printf '\b')
$ sed -e "s/.$BACKSPACE//g" < data | hexdump -C
00000000 62 6f 6c 64 0a |bold.|
根据需要,退格字符和删除的前面字符将从输出中删除(0a
是终止换行符)。