【问题标题】:Shell script to rename file with string from inside file使用内部文件中的字符串重命名文件的 Shell 脚本
【发布时间】:2012-05-28 04:42:09
【问题描述】:

我一直在论坛和 stackoverflow 上搜索这个;它一定在某个地方,但我找不到它。
我在 Mac 上,使用终端运行 shell 脚本,根据文件内容重命名一些 pdf 文件。

我有一个完整的 pdf 目录,我使用开源 pdfbox 将其导出为文本文件。生成的文件与 pdf 文件同名,但以 .txt 结尾。我创建了文本文件,以便可以在文件中找到格式为 Page xx Question xx 的字符串;例如Page 43 Question 2。鉴于此示例,我想将 pdf 文件重命名为 pg43_q2.pdf

我想我想要的正则表达式是这样的: /Page\s+(\d+)Question\s+(\d+) 但我不确定如何读取这两个捕获的数字并将它们保存到我可以用作文件名的字符串中。

我目前的脚本是:

#!/bin/sh
PDF_FILE_PATH=$1
echo "Converting pdfs at $PDF_FILE_PATH"

find "$PDF_FILE_PATH" -name '*.pdf' -print0 | while IFS= read -r -d '' filename; do
   echo $filename
   java -jar pdfbox-app-1.6.0.jar ExtractText "$filename" "$filename.txt"
   NEWNAME=$(sed -n -e '/Page/s/Page\s+\(\d+\)\s+Question\s+\(\d+\).*$/pg\1_q\2/p' "$filename.txt")
   echo "Renaming pdf $filename to $NEWNAME"
   # I would do this next but the $NEWNAME is empty
   # mv "filename" "PDF_FILE_PATH$NEWNAME"
done

...但是 sed 命令没有将任何内容放入 NEWNAME 变量中。

我不是特别喜欢 sed,任何建议都将不胜感激

对脚本的最新编辑使用以下 sed 命令:

newname=$(sed -nE -e '/Page/s/^.*Page[[:blank:]]+([0-9]+)[[:blank:]]+Question[[:blank:]]+([0-9]+).*$/pg\1_q\2.pdf/p' "$filename.txt")

这大约有 50% 的时间有效,但其余时间当我重命名文件时 newname 变量为空。

有效的转换文件的第三行:

Unit 2 Review Page 257 Question 9  a)  12 (2)(2)(3)

转换后的文件第三行不起作用:

Unit 2 Review Page 258 Question 16  a)  (a – 4)(a + 7) = a(a + 7) – 4(a + 7)                             = a2 + 7a – 4a – 28                              = a2 + 3a – 28   b)  (2x + 3)(5x + 2) = 2x(5x + 2) + 3(5x + 2)                                 = 10x2 + 4x + 15x + 6                                 = 10x2 + 19x + 6  c)  (–x + 5)(x + 5) = –x(x + 5) + 5(x + 5)                              = –x2 – 5x + 5x + 25                              = –x2 + 25  d)  (3y + 4)2 = (3y + 4)(3y + 4)                     = 3y(3y + 4) + 4(3y + 4)                     = 9y2 + 12y + 12y + 16                     = 9y2 + 24y + 16  e)  (a – 3b)(4a – b) = a(4a – b) – 3b(4a – b)                                = 4a2 – ab – 12ab + 3b2                                = 4a2 – 13ab + 3b2  f)  (v – 1)(2v2 – 4v – 9) = v(2v2 – 4v – 9) – 1(2v2 – 4v – 9)                                      = 2v3 – 4v2 – 9v – 2v2 + 4v + 9                                      = 2v3 – 6v2 – 5v + 9

【问题讨论】:

    标签: regex bash file-rename


    【解决方案1】:

    删除无用的原始答案

    echo 'Unit 2 Review Page 257 Question 9  a)  12 (2)(2)(3)'\
    | sed -n '/Page/{s/.*Page[ ][ ]*\([0-9][0-9]*\)[ ][ ]*Question[ ][ ]*\([0-9][0-9]*\).*$/pg\1_q\2/;p;q;}'
    

    输出

    pg257_q9
    
    echo 'Unit 2 Review Page 258 Question 16  a)  (a  4)(a + 7) = a(a + 7)  4(a + 7)'\
    | sed -n '/Page/{s/.*Page[ ][ ]*\([0-9][0-9]*\)[ ][ ]*Question[ ][ ]*\([0-9][0-9]*\).*$/pg\1_q\2/;p;q;}'
    

    输出

    pg258_q16
    

    否则,你做对了!

    (请注意,两种情况的 sed 处理是相同的)。

    我包含了一个尾随 ;p;q} 和一个初始 {,因此 sed 脚本只会处理带有“Page”的行,然后退出。

    我已将 posix char 类扩展到基本术语,即 [[:digit:]] = [0-9],并替换了 +,重复初始 char 类,后跟“零或更多” char '*',生成[0-9][0-9]*。我的个人经验是,从 OReilly 的第二版 Sed 和 Awk(带有梳子绑定!)中学习了 Sun 3 上的 sed,所有 posix 的东西都是分散注意力的东西,也是错误的进一步来源。在 S.O 上,我显然是少数派 ;-),但我愿意承认较新的 seds 有一些很棒的功能,无论如何......

    我希望这会有所帮助。

    【讨论】:

    • 有趣!现在,sed 没有返回任何内容,而是在错误的文本文件上得到正确的部分以及该行的所有其余部分。我现在正在尝试调整它,看看我是否可以解决这个问题。
    • 在我的系统上,它显示的是负号,十六进制 D0,它应该与同一文本中的减号相同,但没有区别)。例如,以下文本段 ...Page 258 Question 16 a) (a – 4)(a + 7) = a(... 会导致此输出:pg258_q16? 4)(a + 7) = a(...
    • 如果您仍在使用-E 选项,这可能会导致问题,但我没有要测试的mac。另外,我的 expr [ ] 只是 [$spaceChar]。正确的? (如果您希望腰带和吊带不受任何空白区域的影响,您也应该能够添加 $tabChar ;-) 祝你好运。
    • 另外,我看到十六进制 D0 并不是真正的 std ascii 字符。会做一些研究。必须得走了。祝你好运。
    • @shelter - 谢谢!这给了我一个解决方案的想法,但我必须等到今晚回家才能尝试。 Apache pdfbox 有一个参数 -encoding <output encoding> 在这种情况下,我应该能够将 pdf 仅转换为 ascii,(交叉手指,因为原始 pdf 中有很多 unicode 字符)应该可以解决 sed 的问题与转换后的文本。此外,您发布的解决方案中有一个小错字,在第一次捕获中:*\([0-9][[0-9]*\) 有一个额外的左括号。 :) 所以很高兴你继续和我联系!
    猜你喜欢
    • 2015-06-21
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2013-05-02
    • 2013-11-13
    相关资源
    最近更新 更多