【问题标题】:Why does sed fail when I am trying to extract part of a regex?当我尝试提取正则表达式的一部分时,为什么 sed 会失败?
【发布时间】:2013-09-14 10:53:23
【问题描述】:

我有一个目录中具有以下命名约定的文件列表:prefix_2chars_suffix
示例:currentfile_aa_belongsToprojectForDepcurrentfile_bb_belongsToprojectForDep
我想“提取前缀和后缀之间的 2 个字符。所以我想使用 sed。
我尝试了以下方法:

ls currentfile_* | sed 's/currentfile_\([..]\)_belongsToprojectForDep/\1/g'

我明白了:

sed: -e 表达式#1, char 44: 未知命令: `\'

但是当我这样做时:
echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
它有效,这意味着我的语法没有错误
我在这里做错了什么?

【问题讨论】:

    标签: regex linux bash sed cygwin


    【解决方案1】:

    你不需要把它们放在[]:

    ls currentfile_* | sed 's/currentfile_\(..\)_belongsToprojectForDep/\1/g'
    

    你也可以只使用 cut:

    ls currentfile_* | cut -f 2 -d _
    

    还有一种更准确的形式

    ls currentfile_??_belongsToprojectForDep | cut -f 2 -d _
    

    【讨论】:

    • 删除方括号会给我同样的错误(现在是 char 42)
    • @Jim 你能看到你使用的 sed 版本吗(试试sed --version)?也许 sed 不支持该功能。你也在 bash 还是 shell 中?可以考虑剪裁。
    • 还要确保它仍然在 '' 周围被引用。
    • 我在 cygwin 中使用 sed 4.2.2。您的 cut 有效 (+1) 但我想在 sed 中进行学习
    • 即使在cygwin中也应该没有太大区别。我不确定它是如何不起作用的,但您也可以尝试其他形式:ls currentfile_??_belongsToprojectForDep | sed -r 's|^[^_]+_(..)_.*|\1|'。如果它确实有效,则可能是 sed 中的错误,或者某些字符可能以某种方式有所不同。
    【解决方案2】:

    解析 ls 的输出是非常糟糕的做法。此外,sed 在您的情况下并没有真正有用(即使我在评论中读到您想学习 sed,但您最好学习正确使用正确的工具在给定的情况下——并学会解析ls的输出)。您可以考虑以下纯 bash 解决方案:

    for i in currentfile_??_*; do
        [[ $i =~ ^[^_]+_([^_][^_])_[^_]+$ ]] && echo "${BASH_REMATCH[1]}"
    done
    

    这应该是相当健壮的。如果您将其与 shopt -s nullglob 一起使用,则更加强大。

    • 我们不喜欢解析 ls 的输出。我们使用 glob 代替。在这里,glob 确保我们只循环使用两个下划线由两个字符分隔的文件名。我们这里可能有太多的文件名,例如,currentfile_a__cool_file_is_very_coolcurrentfile____ilikeunderscores__ 这样的文件名会匹配。
    • 在找到的文件名中,我们将使用正则表达式进一步过滤我们想要的文件名,即正好有 2 个下划线(因此由两个非下划线字符分隔)的文件名。
    • ${BASH_REMATCH[1]} 将扩展为第一个匹配模式(注意正则表达式中的括号)。

    第一点是您的 ls-管道的对应部分。最后两点与您的 sed 语句相对应。

    希望这会有所帮助!

    【讨论】:

    • 我不明白 for 循环。它如何知道从例如读取当前目录。 IE。 currentfile.. 是文件名吗?
    • @Jim 这就是 glob 所做的:* 扩展到当前目录中的所有文件。试试看:echo * 将回显当前目录中的所有文件名。 echo *a* 将回显当前目录中包含a 等的所有文件名...实际上,您在执行ls currentfile_* 时已经使用了此功能。
    • We don't like to parse the output of ls 为什么?
    • @Jim This link to Greg's wiki ParsingLs page 应该会给你一些很好的信息,如果你开始解析 ls 的输出,这些问题会让你陷入困境。
    猜你喜欢
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 2022-11-23
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多