SED 和 REGEX 提取,如果未找到模式则拒绝

SED 和 REGEX 提取,如果未找到模式则拒绝

在 SED 命令中,我想删除 2000_SOMENAME 之后的所有内容,如果可能的话,如果找不到该格式,也想给出错误。

例如,如果文件名是ITALY_2022_BEST1FRIENDS2_ROME.txt.我只想2022_BEST1FRIENDS2 在没有找到该模式的情况下在 shell 脚本中给出错误。

username=$(find . -iname '*.txt' | sed -e 's/.*_\([0-9]\{4\}_[0-9|A-z]*\).*/\1/i' | sort - | uniq -ui |tr -d '\n')

上一个问题和更多信息在这里:使用 SED 从文件名中提取部分内容 谢谢你!!

答案1

在这种特殊情况下,使用 grep 可能比使用grep -osed 更有意义,因为如果找不到结果,grep 将退出并出现错误。 (这-o使得它只返回匹配的部分而不是整行。)

棘手的是,您正在通过管道传输到其他命令,并且希望在出现错误时保留退出状态。

如果使用 bash,如果任何组件失败,您可能会导致管道失败set -o pipefailset +o pipefail如果需要,可以将其设置回来以重置它)。

其他 shell 可能也有类似的方法。

set -o pipefail
username="$(find . -iname '*.txt' | grep -o -i '[0-9]\{4\}_[0-9A-Z]*' | sort - | uniq -ui |tr -d '\n')"
# get the exit status of the previous command
pipeexit="$?"
set +o pipefail
if [[ "$pipeexit" != 0 ]] ; then
    echo "username not found" >&2
    # line below quits the script; remove if you don't want that
    exit "$pipeexit"
fi

我遵循您的指导,使模式不区分大小写(-i对 grep;您i在 sed 命令中),并将管道中的其余命令保持不变:我认为您这样做是有原因的。 (虽然这个tr命令看起来很可疑;为什么要把所有结果混在一起放在一行上?)

您还可以考虑一种更简单的方法来检查“错误”:仅检查变量是否$username为空,如果没有 grep 结果,则为空(当然,如果 find 等没有找到 .txt 文件)。 ; 不确定你是否想要那个......)。

username="$(find . -iname '*.txt' | grep -o -i '[0-9]\{4\}_[0-9A-Z]*' | sort - | uniq -ui |tr -d '\n')"
if [ -z "$username" ] ; then
    echo "username not found" >&2
    exit "$pipeexit"
fi

这很可能在其他 shell 中工作......

相关内容