新手问题:ZSH 脚本中的正则表达式

新手问题:ZSH 脚本中的正则表达式

我想我的问题很简单。我想构造一个新的文件名,它有一个固定的前缀和一个数字(两位数字),它是旧文件名的一部分。

示例:我有一个文件“blableblub23.pdf”,我想通过将其重命名为“Newfile 23”来移动它,其中“Newfile”是固定前缀。

所以,首先我必须删除旧文件名中的所有非数字,这是我的主要问题。我正在尝试与

paperno=expr match "$filename" '.*([0-9][0-9]).*'
filename_new="Newfile $paperno"

我总是得到 filename_new = "Newfile" 没有数字,但我期待 "Newfile 23"。

我的错在哪里?

非常非常感谢你 ;)

编辑以澄清:

我有一个文件名(存储在 $filename 中),其中包含文件名中任意位置的两位数,即

Test_bla_blub_23_and_more.pdf Test_23.pdf Test_23_bla.pdf

我只想将数字(示例中为:23)存储在另一个变量 $paperno 中以组成新的文件名。

如果文件名中没有数字或多个数字,则变量 $paperno 应为空或 0。如果有多个数字,如果我返回所有数字,我也会接受。 IE:

Test_12_bla_blub_23_and_more.pdf => $paperno = 1223

抱歉,我对 shell 脚本、zsh 和正则表达式非常陌生......

答案1

zsh对正则表达式匹配有一些内置支持(ERE 和 PCRE),它还具有超出正则表达式的扩展 glob 运算符。无需使用过时且被设计破坏的expr命令(使用 BRE,基本的正则表达式本身)。

它甚至还有一个批量重命名工具:

autoload -Uz zmv
zmv -v '(*[^0-9]|)(<->).pdf' 'Newfile $1'

(*)(<->).pdf,就像.*([0-9][0-9])\.pdf不起作用,因为foo1234.pdf例如,*(resp. .*) 将匹配foo123(resp. foo12) ,只留下最小可能的 ( 4) <->。 (分别34[0-9][0-9])。

如果使用 PCRE,您将能够使用非贪婪匹配运算符,如下所示:

set -o rematchpcre
[[ $file =~ '^.*?(\d+)\.pdf\z' ]]
number=$match[1]

.*不过,如果您不在开头锚定正则表达式,则不需要(在^上面,expr隐式在开头锚定):

[[ $file =~ '(\d+)\.pdf$' ]]

$对于 ERE,默认值,\z在 PCRE 之后set -o rematchpcre)。

或者在这里,您也可以这样做:

zmv '*<->.pdf' 'Newfile ${(M)${f:r}%%<->}'

哪里${f:r}扩展到根名(删除扩展名)的文件,并${(M)param%%pattern}扩展为匹配的参数的最长尾部pattern(此处<->匹配任何 ASCII 十进制数字序列,<x-y>不受限制)。

要从文件名中提取所有数字,例如要foo-123-bar.pdf重命名为Newfile 123foo1bar2.pdf要重命名为Newfile 12

zmv -v '*[0-9]*.pdf' 'Newfile ${f//[^0-9]}'

其中${f//pattern/replacement}展开为$f,所有出现的地方都pattern替换为replacement。这里的替换被省略了,所以我们将除了十进制数字之外的所有字符都替换为空。

为了完整起见,要提取 , 之前的数字列表.pdfexpr您需要执行以下操作:

number=$(expr "x$file" : '.*[^0123456789]\([0123456789]\{1,\}\)\.pdf$')

请记住,如果未找到该数字,它会返回失败退出状态,而且如果它是000000...

x前缀是为了解决expr的设计错误,如果 的扩展$file恰好是一个expr运算符,那么它将被视为运算符。

请注意,这match不是标准expr运算符,标准等效项是该:运算符。

同样,expr它是 70 年代的一个非常破碎和有限的实用程序,在当今时代没有充分的理由继续使用它,特别是zsh它内置了非常强大的文本提取和格式化功能。

答案2

表达式输出是匹配的字符数,您是否尝试打印 paperno 变量?我认为它不会给你预期的输出

可能的方法是去掉所有字符串,然后用“.”剪切,然后你就得到了你的号码。喜欢:

charstostrip=expr match "$filename" '^[a-zA-Z]+$'
modified=${$filename:$charstostrip}
fn_number=${echo $modified | cut -d . -f1}
filename_new="Newfile $fn_number"

相关内容