Bash参数替换混乱(pdfgrep、正则表达式、换行符等)

3

我需要使用pdfgrep在多行中匹配一个模式。

pdfgrep -in -C line 'CHAPTER 1'[$'\n'][$' ']*'THIS IS THE TITLE' ~/temp.pdf

运行正常并输出结果。

12:                                 CHAPTER 1
                  THIS IS THE TITLE

现在
$ pattern="CHAPTER 1 - THIS IS THE TITLE"
$ echo "'${pattern:0:9}'[$'\n'][$' ']*'${pattern:12:${#pattern}}'"
'CHAPTER 1'[$'\n'][$' ']*'THIS IS THE TITLE'
$ pdfgrep -in -C line "'${pattern:0:9}'[$'\n'][$' ']*'${pattern:12:${#pattern}}'" ~/temp.pdf

无法再使用,没有返回结果。我猜测参数替换出了问题,但我无法弄清楚发生了什么。有人能帮忙吗?

背景信息:

来自"man pdfgrep"

pdfgrep works much like grep, with one distinction: It operates on pages and not on lines.

"

"匹配任何字符,包括换行符。

"

2
你的 echo 输出与预期不符 - 你使用了 pattern1 而不是 pattern。这只是问题中的笔误,还是实际上也是如此? - Siguza
2个回答

4
您使用了额外的'字符:
"'${pattern:0:9}'[$'\n'][$' ']*'${pattern:12:${#pattern}}'"
 ^              ^              ^                         ^

此外,您在双引号内使用了$'\n'$' ',这会阻止它们的扩展。
正确的表达式是:
"${pattern:0:9}"[$'\n'][$' ']*"${pattern:12:${#pattern}}"

实际上:
$ echo 'CHAPTER 1'[$'\n'][$' ']*'THIS IS THE TITLE'
CHAPTER 1[
][ ]*THIS IS THE TITLE

$ pattern="CHAPTER 1 - THIS IS THE TITLE"
$ echo "${pattern:0:9}"[$'\n'][$' ']*"${pattern:12:${#pattern}}"
CHAPTER 1[
][ ]*THIS IS THE TITLE

请注意,给定这两个表达式时 echo 命令的输出是相等的(如果你正确操作了的话,echo 不应该返回 Bash 表达式,而应该返回最终字符串)。
虽然不是必需的,但最佳实践是对 *[] 字符加引号(感谢 chepner 的指出)。此外,$' ' 在这里没有用处。
"${pattern:0:9}["$'\n'"][ ]*${pattern:12:${#pattern}}"
                ^     ^  ^

这将防止通配符扩展(虽然在您的情况下不太可能发生,但仍需注意)。

你说得对。我被骗了,因为我不得不在“CHAPTER 1”和“THIS IS THE TITLE”周围加上引号,以避免与空格混淆,而我认为替换完全相同的字符串就可以起作用。 - the_eraser
“[”和“]”也应该被引用;它们形成了有效的模式,shell可以解释(尽管这种模式不太可能匹配文件名)。'CHAPTER 1['$'\n '']*THIS IS THE TITLE...' - chepner

1

当字符串被双引号括起来时,$'\n'不能插入换行符:

prompt $ echo "$'\n'"
$'\n'
prompt $ echo $'\n'

不要在字符串周围使用双引号:

prompt $ a='abcd'$'\n''efgc'
prompt $ echo "$a"
abcd
efgc

P.S.你的正则表达式看起来很奇怪。为什么要在\n和\s周围使用方括号?

我最初使用更简单的命令 pdfgrep -in "CHAPTER 1\n *THIS IS THE TITLE" ~/temp.pdf,然后尝试了 pdfgrep -in "CHAPTER 1$'\n'$' '*THIS IS THE TITLE" ~/temp.pdfpdfgrep -in "CHAPTER 1[$'\n'][$' ']*THIS IS THE TITLE" ~/temp.pdf,但似乎都不起作用。我又加了一些引号,但我真的想不出为什么这些更简单的表达式不起作用。 - the_eraser
我再次尝试,更简单的pdfgrep -in "CHAPTER 1"$'\n'$' '"*THIS IS THE TITLE" ~/temp.pdf成功了! - the_eraser
@the_eraser:如果你想进一步简化它,可以删除 $' ' 并使用 "CHAPTER 1"$'\n'" *THIS IS THE TITLE" - Andrea Corbellini
是的,我做到了。我开始掌握shell脚本编程,这在某些情况下非常棘手,因为需要处理模式匹配、正则表达式、强引用、弱引用、多个替换...有时候这些都要一起处理。谢谢,Luca。 - the_eraser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接