使用 sed 提取文本文件以删除另一个文件中按行给出的后缀

Posted

技术标签:

【中文标题】使用 sed 提取文本文件以删除另一个文件中按行给出的后缀【英文标题】:Stemming a text file to remove suffixes given linewise in another file using sed 【发布时间】:2021-11-14 11:45:21 【问题描述】:

我有一个文件suffix.txt,其中包含一些按行排列的字符串,例如-

ing
ness
es
ed
tion

另外,我有一个文本文件text.txt,其中包含一些文本, 假设text.txt 仅由小写字母组成,没有任何标点符号,例如-

the raining cloud answered the man all his interrogation and with all
questioned mind the princess responded
harness all goodness without getting irritated

我只想为每个后缀从text.txt 中的原始单词中删除后缀一次。因此,我期望以下输出-

the rain cloud answer the man all his interroga and with all
question mind the princess respond
har all good without gett irritat

请注意,tion 并未从 questioned 中删除,因为原始单词不包含 tion 作为后缀。如果有人可以用sed 命令回答这个问题,那将非常有帮助。 我正在使用一个似乎无法完成工作的天真的脚本-

#!/bin/bash

while read p; do
  sed -i "s/$p / /g" text.txt;
  sed -i "s/$p$//g" text.txt;
done <suffix.txt

【问题讨论】:

【参考方案1】:

有点麻烦,但仅限 sed 和 unix 工具:

sed -E -f <(tr '\n' '|' <suffix.txt | sed 's/\|$//; s/\|/\\\\b|/g; s/$/\\\\b/' | xargs printf 's/%s//g') text.txt

tr '\n' '|' <suffix.txt | sed 's/\|$//; s/\|/\\\\b|/g; s/$/\\\\b/' | xargs printf 's/%s//g'

生成替换脚本

s/ing\b|ness\b|es\b|ed\b|tion\b//g

这需要 GNU sed for \b

使用 perl、ruby、awk 等会更容易

这是一个 GNU awk:

gawk -i join 'FNR==NR arr[FNR]=$1; next
FNR==1re=join(arr,1,length(arr),"\\>|"); re=re "\\>"
gsub(re,"")
1
' suffix.txt text.txt

两者都产生:

the rain cloud answer the man all his interroga and with all
question mind the princess respond
har all good without gett irritat

【讨论】:

实际上这并没有提供所需的输出。 您可能没有使用 GNU sed。【参考方案2】:

你可以试试这个sed 方法。

您首先需要从suffix.txt 创建一个数组

suffix=($(cat suffix.txt))

然后您可以在主 sed 代码中使用它进行替换。

sed " s/$suffix[0]//;s/$suffix[1]//g;/question/! s/$suffix[2]//;s/$suffix[3]//g;/question/! s/$suffix[4]//" text.txt

输出

the rain cloud answer the man all his interroga and with all
question mind the princess respond
har all good without gett irritat

【讨论】:

对不起,这至少对我来说似乎不对,对于这个例子,它似乎是硬编码的,而且你在哪里确保 suffix.txt 中的字符串(即后缀数组)实际上是在这个词的结尾?【参考方案3】:

一个 awk:

$ awk '
NR==FNR                    # generate a regex of suffices
    s=s (s==""?"(":"|") $0  # (ing|ness|es|ed|tion)$
    next

FNR==1 
    s=s ")$"                # well, above )$ is inserted here


    for(i=1;i<=NF;i++)      # iterate all the words and
        sub(s,"",$i)        # apply regex to each of them
1' suffix text             # output

输出:

the rain cloud answer the man all his interroga and with all
question mind the princess respond
har all good without gett irritat

【讨论】:

【参考方案4】:

这可能对你有用(GNU sed):

sed -z 'y/\n/|/;s/|$//;s#.*#s/\\B(&)\\b//g#' suffixFile | sed -Ef - textFile

将 suffixFile 转换为文件中的 sed 命令,并通过管道将其传递给修改 textFile 的第二次 sed 调用。

注意sed 命令使用\B\b 来匹配后缀。

【讨论】:

谢谢,它成功了,但是你能解释一下你的代码吗?

以上是关于使用 sed 提取文本文件以删除另一个文件中按行给出的后缀的主要内容,如果未能解决你的问题,请参考以下文章

java 从文件中按行读取文本

Simple Java往文件中按行写入数据

使用 sed 从文本文件中删除特定的行号?

shell脚本--sed的用法

sed命令

linux sed命令