sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename
我希望这个sed脚本能够在$filename
中的每一行的字体中插入一个标签,但事实并非如此。由于某种原因,它插入一个t而不是..奇怪..
答案 0 :(得分:107)
并非sed
的所有版本都理解\t
。只需插入一个文字标签(按 Ctrl - V 然后标签)。
答案 1 :(得分:38)
使用Bash,您可以编程方式插入TAB字符,如下所示:
TAB=$'\t'
echo 'line' | sed "s/.*/${TAB}&/g"
echo 'line' | sed 's/.*/'"${TAB}"'&/g' # use of Bash string concatenation
答案 2 :(得分:22)
@sedit是在正确的道路上,但定义一个变量有点尴尬。
在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
在bash中$'string'
导致" ANSI-C扩展"。这就是我们大多数人在使用\t
,\r
,\n
等内容时所期望的内容。来自:https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting
$' string' 形式的单词将被特别处理。这个词扩大了 到 string ,替换为指定的反斜杠转义字符 ANSI C标准。反斜杠转义序列(如果存在)是 解码...
扩展结果是单引号,好像美元符号没有 在场。
我个人认为大多数避免使用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。 The Open Group在http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16解释了这一点。这是为什么试图避免基本原则通常失败的原因。
答案 3 :(得分:8)
我在Ubuntu 12.04(LTS)上使用了类似的东西和Bash shell:
在第一个匹配时,使用标签添加新行,第二个:
sed -i '/first/a \\t second' filename
用标签替换第一个,第二个:
sed -i 's/first/\\t second/g' filename
答案 4 :(得分:3)
使用$(echo '\t')
。你需要围绕模式引用。
EG。要删除标签:
sed "s/$(echo '\t')//"
答案 5 :(得分:2)
实际上,您不需要使用sed
进行替换,只需在行前面插入一个标签即可。与仅打印出来相比,此案例的替换是一项昂贵的操作,尤其是在处理大文件时。它更容易阅读,因为它不是正则表达式。
例如使用awk
awk '{print "\t"$0}' $filename > temp && mv temp $filename
答案 6 :(得分:1)
答案 7 :(得分:0)
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:])
答案 8 :(得分:0)
而不是BSD sed,我使用perl:
ct@MBA45:~$ python -c "print('\t\t\thi')" |perl -0777pe "s/\t/ /g"
hi
答案 9 :(得分:0)
我认为其他人已经为其他方法(sed
,AWK
等)充分阐明了这一点。但是,接下来是我的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
答案 10 :(得分:0)
TAB=$(printf '\t')
sed "s/${TAB}//g" input_file
它对我在Red Hat上有效,它将从输入文件中删除选项卡。
答案 11 :(得分:0)
如果您知道某些字符没有被使用,您可以将“\t”翻译成别的东西。 cat my_file | tr "\t" "," | sed "s/(.*)/,\1/"