多个模式的一个参数 - grep

Posted

技术标签:

【中文标题】多个模式的一个参数 - grep【英文标题】:One parameter for multiple patterns - grep 【发布时间】:2017-06-08 13:59:08 【问题描述】:

我正在尝试从终端搜索 pdf 文件。我的尝试是从终端提供搜索字符串。搜索字符串可以是一个单词、多个带有 (AND,OR) 的单词或一个精确的短语。我想为所有搜索查询只保留一个参数。我将以下命令另存为 shell 脚本,并将 shell 脚本作为别名从 zsh 或 bash shell 中的 .aliases 调用。

根据 sjr 的回答,这里是:search multiple pdf files。

我用过 sjr 的回答是这样的:

find $1 -name '*.pdf' -exec sh -c 'pdftotext "" - |
      grep -E -m'$2' --line-buffered --label="" '"$3"' '$4'' \;

$1 走路径

$2 限制结果数

$3 是上下文参数(它接受 -A , -B , -C ,单独或联合)

$4 接受搜索字符串

我面临的问题是$4 值。正如我之前所说,我希望这个参数传递我的搜索字符串,它可以是一个短语或一个单词或多个具有 AND / OR 关系的单词。

我无法获得所需的结果,直到现在我才获得短语搜索的搜索结果,直到我关注 Robin Green 的评论。但是短语结果仍然不准确。

编辑判断文本:

The original rule was that you could not claim for psychiatric injury in 
negligence. There was no liability for psychiatric injury unless there was also 
physical injury (Victorian Rly Commrs v Coultas [1888]). The courts were worried 
both about fraudulent claims and that if they allowed claims, the floodgates would 
open. 

The claimant was 15 metres away behind a tram and did not see the accident but 
later saw blood on the road. She suffered nervous shock and had a miscarriage. She 
sued for negligence. The court held that it was not reasonably foreseeable that 
someone so far away would suffer shock and no duty of care was owed.

White v Chief Constable of South Yorkshire [1998] The claimants were police
officers who all had some part in helping victims at Hillsborough and suffered 
psychiatric injury. The House of Lords held that rescuers did not have a special 
position and had to follow the normal rules for primary and secondary victims. 
They were not in physical danger and not therefore primary victims. Neither could 
they establish they had a close relationship with the injured so failed as 
secondary victims. It is necessary to define `nervous shock' which is the rather 
quaint term still sometimes used by lawyers for various kinds of 
psychiatric injury...rest of para

word1可以是:休克,(神经性休克)

word2可以是:精神病学

exact phrase:(神经休克)

命令

alias s='sh /path/shell/script.sh'
export p='path/pdf/files'

在终端:

s "$p" 10 -5 "word1/|word2"          #for OR search
s "$p" 10 -5 "word1.*word2.*word3"   #for AND search
s "$p" 10 -5  ""exact phrase""       #for phrase search

第二个测试样本: 一个示例 pdf 文件,因为命令在 pdf 文档上运行:Test-File。它的 4 页(361 pg 文件的一部分)

如果我们在其上运行以下命令,如解决方案所述:

s "$p" 10 -5 'doctrine of basic structure' > ~/desktop/BSD.txt && open ~/desktop/BSD.txt

我们将获得相关文本并避免遍历整个文件。认为这将是一种很酷的方式来阅读我们想要的东西,而不是采用传统的方法。

【问题讨论】:

为什么投反对票?想知道,以便我以后在提问时可以照顾到。 单引号将导致引用的参数不被扩展(假设您使用的是 bash 或 sh),这不是您想要的。您应该使用双引号来引用 bash 或 sh 中的参数。还是你在使用其他的 shell? 我没有投反对票,我也希望人们在投反对票时能留下反馈。也就是说,将您的问题减少到MCVE (Minimal, Complete, and Verifiable Example) 总是值得的。可以在here 找到有关提问的一般提示。 @RobinGreen,谢谢,我正在使用 zsh,尚未尝试使用 bash。将进一步尝试。 mklement0 感谢您的链接,我正在阅读它们。 到目前为止,您已经展示了代码示例,但没有示例输入/输出。 edit 您的问题包括简洁、可测试的样本输入和预期输出。 【参考方案1】:

你需要:

双引号 命令字符串传递给 sh -c,以便扩展嵌入的 shell 变量引用(然后需要转义 embedded @ 987654322@ 实例为\")。

使用 printf %q 引用正则表达式以安全地包含在命令字符串中 - 请注意,这需要 bashkshzsh 作为 shell。

dir=$1
numMatches=$2
context=$3
regexQuoted=$(printf %q "$4")

find "$dir" -type f -name '*.pdf' -exec sh -c "pdftotext \"\" - |
  grep -E -m$numMatches --with-filename --label=\"\" $context $regexQuoted" \;

这 3 个调用场景将是:

s "$p" 10 -5 'word1|word2'          #for OR search
s "$p" 10 -5 'word1.*word2.*word3'  #for AND search
s "$p" 10 -5 'exact phrase'         #for phrase search

请注意,无需转义|,也无需在exact phrase 周围添加额外的双引号。

另请注意,我已将 --line-buffered 替换为 --with-filename,因为我认为这就是您的意思(以 PDF 文件路径为前缀的匹配行)。


请注意,使用上述方法必须为 每个 输入路径创建一个 shell 实例,这是低效的,因此请考虑重写您的命令如下,这也消除了对 printf %q 的需要(假设regex=$4):

find "$dir" -type f -name '*.pdf' | 
  while IFS= read -r file; do
    pdftotext "$f" - |
      grep -E -m$numMatches --with-filename --label="$f" $context "$regex"
  done

以上假设您的文件名没有嵌入换行符,这在现实世界中很少引起关注。如果是,有办法解决问题。

此解决方案的另一个优点是它仅使用符合 POSIX 的 shell 功能,但请注意 grep 命令使用非标准选项。

【讨论】:

以上是关于多个模式的一个参数 - grep的主要内容,如果未能解决你的问题,请参考以下文章

Linuxgrep命令

多个字符串和模式使用grep

如何用grep中的变量实现多个模式?

当我找到多个 pdf 文件、xarg pdftotext 和 grep 模式时,文件名丢失

shell:正则表达式和文本处理

三剑客之grep