在 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 -o
sed 更有意义,因为如果找不到结果,grep 将退出并出现错误。 (这-o
使得它只返回匹配的部分而不是整行。)
棘手的是,您正在通过管道传输到其他命令,并且希望在出现错误时保留退出状态。
如果使用 bash,如果任何组件失败,您可能会导致管道失败set -o pipefail
(set +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 中工作......