为什么sed没有将 t识别为标签?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么sed没有将 t识别为标签?相关的知识,希望对你有一定的参考价值。

sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename

我期待这个sed脚本在$filename的每一行的字体中插入一个标签,但事实并非如此。由于某种原因,它插入一个t代替..奇怪..

答案

并非所有版本的sed都了解\t。只需插入一个文字标签(按Ctrl-V然后按Tab键)。

另一答案

我认为其他人已经充分澄清了其他方法(sedAWK等)。但是,我的bash特定答案(在macOS High Sierra和CentOS 6/7上测试)如下。

1)如果OP想要使用类似于他们最初提出的搜索和替换方法,那么我建议使用perl,如下所示。注意:正则表达式的正则表达式之前的反斜杠不应该是必需的,并且此代码行反映了$1如何比使用\1替换运算符的perl更好(例如,每个Perl 5 documentation)。

perl -pe 's/(.*)/\t$1/' $filename > $sedTmpFile && mv $sedTmpFile $filename

2)但是,正如ghostdog74所指出的那样,因为在将tmp文件更改为输入/目标文件($filename)之前,所需的操作实际上只是在每行的开头添加一个制表符,我会再次推荐perl但是以下修改:

perl -pe 's/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename
## OR
perl -pe $'s/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename

3)当然,tmp文件是多余的,所以最好只做“就地”(添加-i标志)并将事情简化为更优雅的单行程序

perl -i -pe $'s/^/\t/' $filename
另一答案

使用Bash,您可以编程方式插入TAB字符,如下所示:

TAB=$'\t' 
echo 'line' | sed "s/.*/$TAB&/g" 
echo 'line' | sed 's/.*/'"$TAB"'&/g'   # use of Bash string concatenation
另一答案

@sedit是在正确的道路上,但定义一个变量有点尴尬。

Solution (bash specific)

在bash中执行此操作的方法是在单引号字符串前放置一个美元符号。

$ echo -e '1\n2\n3'
1
2
3

$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3

$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
    1
    2
    3

如果您的字符串需要包含变量扩展,您可以将引用的字符串放在一起,如下所示:

$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958  1
1491237958  2
1491237958  3

Explanation

在bash中$'string'导致“ANSI-C扩展”。这就是我们大多数人在使用\t\r\n等等时所期望的。来自:https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

$'string'形式的单词是专门处理的。单词扩展为字符串,替换为ANSI C标准指定的反斜杠转义字符。反斜杠转义序列(如果存在)将被解码...

扩展结果是单引号,好像美元符号不存在一样。

Solution (if you must avoid bash)

我个人认为大多数避免使用bash的努力都是愚蠢的,因为避免使用bashisms并不能使你的代码可移植。 (如果你把它放到bash -eu,你的代码会比你试图避免使用sh [除非你是一个绝对的POSIX忍者]而不那么脆弱。)但是我不会就此做出宗教争论,我会给你最好的答案。

$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
    1
    2
    3

* 最佳答案?是的,因为大多数反bash shell脚本编写者在他们的代码中会出错的一个例子是在echo '\t'中使用@robrecord's answer。这适用于GNU echo,但不适用于BSD echo。这是由http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16的开放组解释的。这是为什么试图避免基本原则通常失败的一个例子。

另一答案

我在Ubuntu 12.04(LTS)上使用了类似的东西和Bash shell:

要添加带选项卡的新行,请在第一个匹配时添加第二行:

sed -i '/first/a \\t second' filename

首先用tab替换,第二个:

sed -i 's/first/\\t second/g' filename
另一答案

实际上,您不需要使用sed进行替换,您只需要在该行前面插入一个选项卡。与仅打印出来相比,此案例的替换是一项昂贵的操作,尤其是在处理大文件时。它更容易阅读,因为它不是正则表达式。

例如使用awk

awk 'print "\t"$0' $filename > temp && mv temp $filename
另一答案

使用$(echo '\t')。你需要围绕模式引用。

例如。要删除标签:

sed "s/$(echo '\t')//"
另一答案

我在Mac上用过这个: -

sed -i '' $'$i\\\n\\\thello\n' filename

Used this link for reference

另一答案

sed不支持\t,也不支持像\n这样的其他逃脱序列。我发现这样做的唯一方法是使用sed在脚本中插入制表符。

也就是说,您可能需要考虑使用Perl或Python。这是我写的一个简短的Python脚本,我用于所有流正则表达式:

#!/usr/bin/env python
import sys
import re

def main(args):
  if len(args) < 2:
    print >> sys.stderr, 'Usage: <search-pattern> <replace-expr>'
    raise SystemExit

  p = re.compile(args[0], re.MULTILINE | re.DOTALL)
  s = sys.stdin.read()
  print p.sub(args[1], s),

if __name__ == '__main__':
  main(sys.argv[1:])
另一答案

而不是BSD sed,我使用perl:

ct@MBA45:~$ python -c "print('\t\t\thi')" |perl -0777pe "s/\t/ /g"
   hi

以上是关于为什么sed没有将 t识别为标签?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Qt::mightBeRichText() 不能将 HTML 表格标签识别为富文本?

我可以在 vue js 中创建一个带有循环的组件吗?有没有办法让它被识别为html标签?

Wit.ai 将数字识别为位置

为啥此代码无法将 lista 识别为列表? [关闭]

为啥我的 MongoDB ObjectID 没有被识别为 TypeScript 中的类型?

无法将“slmgr”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。如何解决?