我想找到一个单词在文本文件中出现的位置——比如一个单词出现在文本中的单词数量——对于该单词的所有实例,但我什至不确定从哪里开始。我想我需要一个循环,以及 grep 和 wc 的某种组合。
例如,这里有一篇关于 iPhone 11 的文章:
周二,该公司表示,其入门级手机 iPhone 11 的起价为 700 美元,而上一款同类机型的起价为 750 美元,这表明苹果正在关注那些不会竞相购买更昂贵手机的消费者。年。
苹果将其更先进的机型 iPhone 11 Pro 和 iPhone 11 Pro Max 的起价保持在 1,000 美元和 1,100 美元。该公司在其硅谷园区举行的 90 分钟新闻发布会上推出了这些新手机。
正文共有81个字。
jaireaux@macbook:~$ wc -w temp.txt
81 temp.txt
“iPhone”这个词出现了 3 次。
jaireaux@macbook:~$ grep -o -i iphone temp.txt | wc -w
3
我想要的输出是这样的:
jaireaux@macbook:~$ whereword iPhone temp.txt
24
54
57
我会怎么做才能得到那个输出?
这是使用 GNU 工具的一种方法:
第一个
tr
用换行符替换所有空格,然后第二个删除所有标点符号(以便iPhone,
可以作为单词找到)。确保我们跳过任何空grep .
行(我们不想计算那些)grep -n
并将行号附加到输出中。然后,-F
告诉grep
不要将其输入视为正则表达式,并且-x
它应该只找到跨越整行的匹配项(因此这job
不会算作 的匹配项jobs
)。请注意,您在问题中给出的数字相差 1。如果您只想要数字,您可以添加另一个步骤:
正如评论中所指出的,这仍然会有“单词”的问题,例如
aren't
ordouble-barreled
。您可以使用以下方法进行改进:使用 tr 命令将所有空格替换为单个换行符(使用挤压选项)。
将其传递给 nl -ba,它会按顺序对每一行(以及单词)进行编号。
将它传递给 grep -F 以获得您想要的单词。这将仅显示这些单词的数字和文本。
awk 也可以在一个进程中执行此操作,但可能看起来更复杂。
一个替代方案
sed
:输出:
我正在尝试(现在!)类似的东西:字数。像这样,您会看到“单词”的样子:
这个技巧(?)
|sort|uniq -c|sort -n
提供了一个很好的概述。这看起来不错,但在顶部:
美元、逗号和减号都不见了……至少看起来很干净。
一个快速的解决方法是定义一些不会出现在(自然语言)“单词”中的常见插句。然后在一侧或两侧使用 ^anchoring$。
你可以找到小数字之类的东西:
tr|sed|grep
(最好的简单解决方案)这会处理一些情况(以及这个@*#!文本中的所有情况;)并给出 81 个单词,例如
wc
. 编号必须没有前导空格才能正确。愚蠢的(但不是太)拆分由 完成tr
,然后sed
删除尾随标点符号:这里只有逗号和句点。然后是grep
数字和过滤器即兴发挥。这找不到复数形式
i*[pP]hone$
。这不适用于尾随逗号,请参见上文。逗号不见了,除了价格。要分隔“入门级”,您只需将减号添加到
tr
SET1。我认为这是每个工具执行一个自然步骤的一个很好的例子。
创建一个函数。
[我想知道你是如何得到这些数字的——如果我选择第一个文本
iPhone
并将其传送到wc -w
,我得到 24。在第二个之前iPhone
,我得到 53,而不是 54。所以它们不匹配,无论在哪个我改变他们的方向]假设a)计数应该是从 1 开始的,b)单词用空格分隔(使用与 相同的“单词”定义
wc -w
),并且c)使用 GNU grep,这会更简单:[也将匹配
iPhoney
orXiPhone
,但不匹配iphone
; 如果您想让它不区分大小写地匹配整个单词,请使用... | grep -nwi iPhone
]这也更容易适应“词”的不同定义;例如,对于 word = 除控件、空格(分隔符)和标点之外的任何字符的序列:
或 word = 字母、标记、数字和一些符号和标点符号,如
$
,_
,'
+ 使用不当的“左引号”(U+2019)代替撇号aren’t
:使用“单词”的最常见解释来解析英文文本(即什么
grep -w
认为一个单词以及\w
在工具中接受它作为正则表达式中的“单词组成字符”的含义),即“一串字母、数字和/或下划线字符”aren’t
不是一个词,所以:或者如果
aren’t
是一个词,那么:正确的解决方案完全取决于您对“单词”的定义。例如,以上都不
$1,000
是一个词——如果这对您的应用程序来说是个问题,那么 idk 。如果是,这里的脚本可能更接近您对“单词”的解释(使用 GNU awk 进行 FPAT):这是它在您的示例输入中识别的“单词”:
一个 GNU
awk
替代方案,在单个空格上拆分或句号和换行符的组合为了跟上一个词就是一个词的想法
wc
:我们可以用 将文件分成每行中的非空格序列
grep -Eo '[^[:space:]]+' file
,然后删除tr -d '[:punct:]'
(仍然存在的)标点符号,最后,通过感兴趣的单词 grep(不区分大小写)grep -in 'phone'
请注意,在这种情况下删除标点符号不会改变单词的行位置。该
-i
选项同时选择Phone
和phone
,如图所示。对于单词的情况
iPhone
:那应该是正确的单词编号(不是您写的 24、54 和 58)。