我要在字符串上应用Unix命令 sed (可以包含#,!,/,?,&,@和所有其他字符)可以包含所有类型的字符(&,|,!,/,?...)
它是一个复杂的分隔符(有两个字符?),它可以允许超越错误:
sed: -e expression #1, char 22: unknown option to `s'
提前致谢
答案 0 :(得分:13)
输入文件中的字符无关紧要 - sed
可以解析它们。但是,如果您的模式中包含大多数常见字符,或者您的模式可能事先未知,则可能会出现问题。
至少在GNU sed上,您可以使用不可打印的字符,该字符在您的模式中作为分隔符存在极不可能。例如,如果您的shell是Bash:
$ echo '|||' | sed s$'\001''|'$'\001''/'$'\001''g'
在此示例中,Bash replaces $'\001'
的字符具有八进制值001
- 在ASCII中,它是SOH字符(标题的开头)。
由于这些字符是控制/不可打印的字符,因此它们将存在于模式中是值得怀疑的。除非,即你正在做一些奇怪的事情,如修改二进制文件 - 或没有正确的语言环境设置的Unicode文件。
答案 1 :(得分:2)
另一种方法是使用Shell参数替换。
${parameter/pattern/replace} # substitute replace for pattern once
或
${parameter//pattern/replace} # substitute replace for pattern everywhere
这是一个非常复杂的例子,很难用sed:
$ parameter="Common sed delimiters: [sed-del]"
$ pattern="\[sed-del\]"
$ replace="[/_%:\\@]"
$ echo "${parameter//$pattern/replace}"
结果是:
Common sed delimiters: [/_%:\@]
但是: 这仅适用于bash参数,而不适用于sed
擅长的文件。
答案 2 :(得分:1)
sed中没有多字符表达式分隔符的选项,但我对此表示怀疑 你需要那个。分隔符字符不应出现在模式中,但如果它出现在正在处理的字符串中,则不是问题。除非你做的事非常奇怪,否则总会有一些字符在你的搜索模式中没有出现,可以作为分隔符。
答案 3 :(得分:1)
您需要Perl提供的嵌套分隔符工具。这允许使用匹配,替换和音译之类的东西,而不必担心内容中包含分隔符。由于perl是sed的超集,所以你应该可以将它用于你用过的任何东西。
考虑一下:
$ perl -nle 'print if /something/' inputs
现在,如果您的something
包含斜杠,则表示您遇到了问题。解决此问题的方法是更改分隔符,最好是更改分隔符。因此,例如,您可以在$ WHATEVER shell变量中拥有任何您喜欢的内容(假设支持是平衡的),在Perl甚至在此处调用之前由shell进行插值:
$ perl -nle "print if m($WHATEVER)" /usr/share/dict/words
即使你在$ WHATEVER中正确嵌套了parens,它也能正常工作。在Perl中正确嵌套的四个包围对是< >
,( )
,[ ]
和{ }
。如果该分隔符是平衡的,它们允许包含分隔符的任意内容。
如果不平衡,则根本不要使用分隔符。如果模式位于Perl变量中,则只要使用=~
运算符,就不需要使用匹配运算符,因此:
$whatever = "some arbitrary string ( / # [ etc";
if ($line =~ $whatever) { ... }
答案 4 :(得分:1)
在Jim Lewis的帮助下,我在使用sed之前终于做了一个测试:
if [ `echo $1 | grep '|'` ]; then
grep ".*$1.*:" $DB_FILE | sed "s@^.*$1*.*\(:\)@@ "
else
grep ".*$1.*:" $DB_FILE | sed "s|^.*$1*.*\(:\)|| "
fi
感谢您的帮助
答案 5 :(得分:1)
转换内联分隔符以便BASH进行解析很麻烦且难以阅读(尽管分隔符确实需要在首次使用,表达式时才能获得sed的好处。)
汇总thkala的答案和user4401178的评论:
DELIM=$(echo -en "\001");
sed -n "\\${DELIM}${STARTING_SEARCH_TERM}${DELIM},\\${DELIM}${ENDING_SEARCH_TERM}${DELIM}p" "${FILE}"
此示例返回从${STARTING_SEARCH_TERM}
开始的所有结果,直到${ENDING_SEARCH_TERM}
与{1}}(标题的开头)字符匹配,并且ASCII码为001。
答案 6 :(得分:0)
哇。我完全不知道你可以使用任何字符作为分隔符。 至少有一半的时间我使用sed和BREs的路径,代码片段,垃圾字符,类似的东西。我最终得到了一堆可怕的难以理解的逃脱,我甚至不确定不会因为我没想到的某些组合而死。但是如果你只能排除一些角色类(或者只是一个角色)
echo '#01Y $#1+!' | sed -e 'sa$#1+ashita' -e 'su#01YuHolyug'
> > > Holy shit!
那是所以更容易。
答案 7 :(得分:0)
没有通用的分隔符,但是sed可以将其反斜杠转义,以使其不像分隔符一样对待(至少除非选择反斜杠字符作为分隔符)。
根据实际应用,仅在模式和替换中转义这些字符可能会很方便。
如果您处于bash环境中,则可以使用bash替换来逃脱sed分隔符,如下所示:
temp2
除了离奇的部分,这很不言自明。 对此的解释:
if(temp.length() == 0) return "";
示例用法:
safe_replace () {
sed "s/${1//\//\\\/}/${2//\//\\\/}/g"
}