我想我的问题很简单。我想构造一个新的文件名,它有一个固定的前缀和一个数字(两位数字),它是旧文件名的一部分。
示例:我有一个文件“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 123
或foo1bar2.pdf
要重命名为Newfile 12
:
zmv -v '*[0-9]*.pdf' 'Newfile ${f//[^0-9]}'
其中${f//pattern/replacement}
展开为$f
,所有出现的地方都pattern
替换为replacement
。这里的替换被省略了,所以我们将除了十进制数字之外的所有字符都替换为空。
为了完整起见,要提取 , 之前的数字列表.pdf
,expr
您需要执行以下操作:
number=$(expr "x$file" : '.*[^0123456789]\([0123456789]\{1,\}\)\.pdf$')
请记住,如果未找到该数字,它会返回失败退出状态,而且如果它是0
或00
,000
...
该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"