我知道我可以用来awk
解析多个分隔符,但这会产生子进程。我想知道复合/嵌套 bash 参数扩展是否可能。
我的 PDF 文件位于名为“Px_MM-DD-YY_SSSSSSSSSS.pdf”的目录中,其中:
- “Px”表示“第 x 页”,并且 x 没有前导零。
- “MM”对应于两位数月份,如果适用,则带有前导零。
- “DD”对应两位数的日期,如果适用,则带有前导零。
- “YY”对应两位数年份,如果适用,则带有前导零。
- “SSSSSSSSSS”对应于创建 PDF 的十位数纪元时间,这允许我保留 PDF 页面修订。
我有一个 for 循环(当我准备好对所有 PDF 进行操作时,我会删除“-mtime”)
for file in $(find -type f -iname '*_??????????.pdf' -mtime -1)
do
echo $file
done
我只想回显纪元时间。
我可以使用这个 for 循环
for file in $(find -type f -iname '*_??????????.pdf' -mtime -1)
do
echo ${file##*_}
done
对于名为“./P14_07-21-18_4X_1532144458.pdf”的文件,“1532144458.pdf”会回显到屏幕上。
我可以使用这个 for 循环
for file in $(find -type f -iname '*_??????????.pdf' -mtime -1)
do
echo ${file%.*}
done
对于名为“./P14_07-21-18_4X_1532144458.pdf”的文件,“./P14_07-21-18_4X_1532144458”会回显到屏幕上。
如果我echo ...
用下面的任何格式替换该行
echo ${${file##*_}:0:10}
echo ${(${file##*_}):0:10}
echo ${${file##*_}%.*}
echo ${{file%.*}##_}
echo ${${file%.*}##_}
我明白了-bash: ... : bad substitution
。我的语法是否正确,或者嵌套/复合 bash 扩展不可能?
答案1
您无法执行嵌套替换变量在最左边的部分。所以你可以做${foo#$bar}
,但不能做你所展示的。
如果您想在进一步的替换中使用替换结果,请将替换结果放入变量中。
答案2
如果不首先将初始结果保存到变量并对其应用第二次替换,则无法让参数替换对另一个参数替换的结果起作用。
您还可以循环输出find
,其中不推荐。
为循环提供结果的正确方法find
是调用子 shell 并在其中执行循环:
find . -type f -iname '*_??????????.pdf' -mtime -1 -exec sh -c '
for pathname do
timestamp=${pathname##*_} # remove up to last _
timestamp=${timestamp%.pdf} # remove .pdf
printf "pathname=%s\ttimestamp=%s\n" "$pathname" "$timestamp"
done' sh {} +
这样,您就不必担心实际的路径名是什么。 Unix 中的文件名(即文件、目录和其他文件类型的名称)可以包含除 和 之外的任何字符/
,\0
例如空格和换行符。通过在 上使用命令替换find
,您可以强制 shell 首先执行分词(默认情况下在空格、制表符和换行符上),然后根据从 . 返回的路径名中找到的模式执行文件名生成find
。因此,您的原始循环可能最终会循环与您预期完全不同的单词。
有关的:
答案3
如果我理解正确的话,使用 Awk 的问题在于您要为每个 PDF 文件调用一个 Awk 进程(我假设您有大量这样的文件)。
你可以按照以下方式运行一些东西
find . ...... -print0 | perl -0nE '/.*_(\d{10}).pdf/ and say "$1.pdf"'
或者如果你保持结构:
for file in $(find .....| perl ....)
do
...
done
(当然,用任何 Awk、sed、Python 等效命令替换 Perl 命令)
(如果您有机会尝试这种方法请告诉我们time ....
获得的结果)