【问题标题】:Sed command keeps on throwing error "Unrecognized Command"Sed 命令不断抛出错误“无法识别的命令”
【发布时间】:2016-10-18 14:02:27
【问题描述】:

我在执行 sed 命令时遇到问题。我想先知道 sed 命令是否真的在处理 ksh 脚本。我使用 putty 作为我的工具来执行 ksh 脚本。

如果它真的有效,我使用的命令是sed -e [^a-zA-Z0-9] <file>

我实际上是为 grep 执行此命令,grep [^a-zA-Z0-9] <file>

我的目标是获取文本文件中的所有特殊字符并将其返回到变量或其他文件。我正在为这个网站和所有其他网站寻找这个,但我从来没有找到任何真正适合我的网站。

【问题讨论】:

    标签: unix sed grep


    【解决方案1】:

    您的不是有效的sed 脚本。缺少引用加剧了这个问题。

    如果没有引号,shell 会尝试将表达式 [^a-zA-Z0-9] 扩展为匹配文件名的列表。如果您在当前目录中有名为,? 的文件,则即使在grep 运行之前,glob 也会扩展为grep , ? <file>(也取决于您的shell 设置——使用shopt -s nullglob 模式例如,如果没有匹配项,则会消失)。

    sed 的语法不同。要将正则表达式与sed 匹配,请使用

    sed '/[^a-zA-Z0-9]/' <file>
    

    斜线是可配置的;例如,如果你有一个包含斜杠的正则表达式,你可以通过在它前面加上一个反斜杠来使用不同的分隔符:

    sed '\#[^a-zA-Z0-9/]#' <file>
    

    如果您只想提取匹配的字符,请尝试grep -o -- 再次注意正确引用您的变量。

    chars=$(grep -o '[^a-zA-Z0-9]' <file>)
    echo "$chars"  #  double quotes are *absolutely* *crucial*
    

    如果没有双引号,shell 会再次尝试将 chars 中的任何 * 扩展为当前目录中的文件列表。

    【讨论】:

    【解决方案2】:

    sed 是您的 shell 外部的二进制实用程序。你可以看到它在哪里

    $ which sed
    /usr/bin/sed
    

    您的既定目标是使用sed 和/或grep 从文本文件中获取所有“特殊”字符,其中特殊字符是不在集合 a-z、A-Z 或 0- 中的任何字符9.使用sed 最简单:

    $ sed -e 's/[a-zA-Z0-9]//g' file
    

    这会将所有非特殊字符替换为空字符,从而有效地将它们从文件中删除。使用/etc/passwd 作为输入的示例将输出类似于此的内容:

    $ sed -e 's/[a-zA-Z0-9]//g' /etc/passwd
    :::::/://
    :::::/://
    :::::/://
    ::::://://
    :::::///://
    :::::/://
    :::::/://
    :::::/://
    :::::///://
    :::::/://
    ::::://://
    :::: ://://
    :::::/://
    :::::///://
    -::::  :/://
    -::::  :/://
    -:::: :/://
    --::::  :/://
    

    对于grep,您可以使用-o 选项输出匹配值:

    $ grep -o '[^a-zA-Z0-9]' /etc/passwd
    

    这将产生类似的输出,但是,每个匹配的字符都会出现在新的一行中。

    另一个选项是tr:

    $ tr -d '[:alnum:]' </etc/passwd
    

    这将产生与之前的sed 命令相同的输出。


    在所有三种情况下,您都可以像这样捕获命令的标准输出:

    $ specials=$(tr -d '[:alnum:]' </etc/passwd)
    $ echo $specials
    :::::/:// :::::/:// :::::/:// ::::://:// :::::///:// :::::/:// :::::/:// :::::/:// :::::///:// :::::/:// ::::://:// :::: ://:// :::::/:// :::::///:// -:::: :/:// -:::: :/:// -:::: :/:// --:::: :/:// :::: :/:// :::: :/:// :::: :///:// :::: :///:// ::::://:// :::: ://:// :::::/:// :::: :///:// :::::///:// :::: /- :///-:// :::::///:// :::: :///:// :::: :/:// :::::///:// ::::://:// -:::: :/:// :::: :/:// :::: ://:// :::: :/:// :::: :///:// :::: :///:// --::::://--/:// -:::: :/:// ::::- :///:// :::: ://:// :::::/:// ::::://:// ::::://:// :::: ://:// :::: :///:// :::: :///:// :::: :///://
    

    使用反引号也可以:

    $ specials=`tr -d '[:alnum:]' </etc/passwd`
    

    【讨论】:

    • 不引用 echo "$specials" 之类的变量可能会产生令人惊讶且难以调试的效果,如我之前的回答中所述。
    • 谢谢! :) 这个对我有用 grep -o '[^a-zA-Z0-9]'。
    • @JMM:没问题。所有 3 个选项都有效。如果您对答案感到满意,您可以考虑接受它。
    • @mhawke 接受它是什么意思?我很抱歉我只是这个网站的新手。有什么我可以点击的按钮吗?
    猜你喜欢
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2013-07-06
    • 2015-08-02
    相关资源
    最近更新 更多