【问题标题】:How to Remove duplication of words from both sentences using shell script?如何使用 shell 脚本从两个句子中删除重复的单词?
【发布时间】:2020-12-18 11:31:07
【问题描述】:

我有一个包含重复单词的两个句子,例如文件my_text.txt中的输入数据:

Unix 和 Linux 操作系统。
Unix和Linux系统是为了创造一个环境 这促进了高效的计划。

我使用了这个脚本:

while read p
do
echo "$p"|sort -u | uniq
done < my_text.txt

但是输出和输入文件的内容是一样的:

Unix 和 Linux 操作系统。 Unix和Linux系统是为了创造一个促进高效程序的环境

如何从两个句子中删除重复的单词?

【问题讨论】:

  • 能否请您在问题中发布更清晰的输入和预期输出示例,以便更好地理解问题。
  • 我想删除两个句子中的所有重复词,在我的示例中,两个句子中有 5 个重复词(The、Unix 和 ,Linux、system),但我需要一个更通用的脚本对于包含重复单词的两个句子。

标签: bash shell unix uniq


【解决方案1】:

您的代码将删除重复的行; sortuniq 都在行上操作,而不是单词。 (即使那样,循环也是多余的;如果你想这样做,你的代码应该被简化为sort -u my_text.txt。)

通常的解决方法是将输入拆分为每行一个单词;现实世界的文本有一些复杂性,但第一个基本的 Unix 101 实现看起来像

tr ' ' '\n' <my_text.txt | sort -u

当然,这会以与原始单词不同的顺序为您提供单词,并保存每个单词的第一次出现。如果您想丢弃任何多次出现的单词,不妨试试

tr ' ' '\n' <my_text.txt | sort | uniq -c | awk '$1 == 1 { print $2 }'

(如果您的tr 无法将\n 识别为换行符,不妨试试'\012'。)

这是一个非常简单的两遍 Awk 脚本,希望它更有用一点。它在第一次遍历文件时将所有单词收集到内存中,然后在第二次中删除任何出现多次的单词。

awk 'NR==FNR { for (i=1; i<=NF; ++i) ++a[$i]; next }
{ for (i=1; i<=NF; ++i) if (a[$i] > 1) $i="" } 1' my_test.txt my_test.txt

这会在单词被删除的地方留下空白;使用最终的sub() 来解决这个问题应该很容易。

一个更有用的程序会拆分任何标点符号,并将单词缩减为小写(这样WordwordWord!word? 就不算单独)。

【讨论】:

    【解决方案2】:

    可以使用此命令从两个句子中删除重复的单词:

    tr ' ' '\n' <my_text.txt | sort | uniq | xargs 
    
    

    【讨论】:

      【解决方案3】:

      使用 awk (GNU awk):

       awk '{ 
              for (i=1;i<=NF;i++) { # Loop on each word on each line
                gsub(/[[:punct:]]/,"",$i); # Srip out any punctuation
                cnt++; Set a word count variable
                if (!map[$i]) { If there is not an entry for the word in an array, set it with the word as the index and the cnt variable as the value
                  map[$i]=cnt 
                } 
               } 
            } 
        END { 
              PROCINFO["sorted_in"]="@val_num_asc"; # Set the order of the array to value number ascending
              for (i in map) { 
                 printf "%s ",i # Print each word with a space
              } 
             }' filename
      

      一个班轮:

       awk '{ for (i=1;i<=NF;i++) { gsub(/[[:punct:]]/,"",$i);cnt++;if (!map[$i]) { map[$i]=cnt } } } END { PROCINFO["sorted_in"]="@val_num_asc";for (i in map) { printf "%s ",i } }' filename
      

      注意 - 这将删除任何标点符号(单词后的句号)

      【讨论】:

        【解决方案4】:

        要输出保留单词出现顺序的已处理行,您可以使用awk 解析并删除重复项。此脚本支持多个句子,考虑到单词后跟常用标点符号 (.,;):

        文件remove_duplicates.awk

        #!/usr/bin/awk -f
        
        {
            # Store occurences of each word in current line, keyed by the word itself
            for (i=1; i<=NF; i++) {
                sub(/[.,;]/, "", $i)
                seen_words[$i]++
            }
            # Store line, keyed by line number
            lines[$NR]=$0
        }
        END {
            # Process stored lines
            for (i=1; i<=NR; i++) {
                split(lines[$i], word, " ")
                output_line=""
                for (j=1; j<=length(word); j++){
                    sub(/[.,;]/, "", word[j])
                    if (seen_words[word[j]] <= 1) {
                        output_line = output_line " " word[j]
                    }
                }
                print output_line
            }
        }
        

        用法:

        ./remove_duplicates.awk < input_text
        

        输出:

        operating
        was to create an environment that promoted efficient program
        

        【讨论】:

        猜你喜欢
        • 2021-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-01
        • 1970-01-01
        • 2016-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多