sed rare-delimiter(& | /?...除外)

时间:2011-01-30 19:07:28

标签: sed delimiter

我要在字符串上应用Unix命令 sed 可以包含#,!,/,?,&,@和所有其他字符)可以包含所有类型的字符(&,|,!,/,?...)

它是一个复杂的分隔符(有两个字符?),它可以允许超越错误:

sed: -e expression #1, char 22: unknown option to `s'

提前致谢

8 个答案:

答案 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"
}