让正则表达式匹配文件名

让正则表达式匹配文件名

我有一个脚本,可以列出符合特定条件的一组文件。它仅输出文件名,并且有一堆不必要的文本。

示例字符串为:

[gg]_Magi_-_13_[DB38165F].mkv

我想在输出中实现的是:

[gg]_Magi_-_13

我已经能够替换下划线,但无法成功修剪 [CRC32].mkv。此外,我还限制了字符数,如果字符数超过 28 个字符,则在末尾添加省略号,但即使字符数不超过 28 个字符,它仍会在末尾附加省略号。
代码如下:

print substr( $0, 0, 28 )"[…]"}

对于这些问题的帮助将不胜感激。

答案1

虽然awksed和 公司 各有优点,但它们并不是必需的。您只需使用bash字符串操作和模式匹配即可轻松实现您要求的一切。假设您已将文件名分配给$name

name="${name%_\[*\].*}"

将从中截断文件类型和括号内的 CRC $name。如果您需要 100% 确保只截断 CRC,则可以使用扩展正则表达式代替上述内容:

[[ $name =~ (.*)_\[[[:xdigit:]]{8}\]\..*$ ]] && name="${BASH_REMATCH[1]}"

然后通过以下方式截断长度超过 28 个字符的名称:

(( ${#name} > 28 )) && name="${name::27}…"

– 总共两行bash(不包括逻辑、循环或其他,将文件名放入 var,当然还有输出代码),没有外部代码。主要优点是代码速度极快,因为 shell 永远不需要启动任何外部二进制文件。

答案2

我认为满足所有条件的最短解决方案就是这个

awk '{
    if (match($0, "^(.*)_[^_]+$", a)) {
        print substr(a[1], 1, 27) (length(a[1]) > 27 ? "..." : "")
    }
}'

答案3

sed -e 's/_\[.*\.mkv//' -e 's/^\(.\{28\}\).*/\1.../' file.txt

第一位去掉_[blah].mkv,第二位打印前 28 个字符,并将 放在...末尾 - 但如果字符串少于 28 个字符,它只会打印去掉的文件名,而不会添加省略号。

如果文件的扩展名不总是 *.mkv,您可以使用这个(在 sed 中,$表示“到行尾”):

sed -e 's/_\[.*$//' -e 's/^\(.\{28\}\).*/\1.../' file.txt

答案4

这不是最干净的解决方案,但你可以这样做:

 echo "[gg]_Magi_-_13_[DB38165F].mkv" | awk -F '_' '{print $1"_"$2"_"$3"_"$4}'

编辑:嗯,删除这个答案。它不会给你省略号。

相关内容