【问题标题】:Bash script to store list of files in an array with number of occurrences of each word in all filesBash脚本将文件列表存储在数组中,其中每个单词在所有文件中的出现次数
【发布时间】:2014-09-14 18:35:38
【问题描述】:

到目前为止,我的 bash 脚本有两个参数……输入可以是文件或目录,输出可以是输出文件。它递归地查找所有文件,如果输入是一个文件,它会在找到的所有文件中查找每个单词的所有出现,并在输出文件中列出它们,左侧的数字和右侧的单词从大到小排序。现在它也将数字计算为它不应该做的单词......我怎么能让它只找到所有出现的有效单词而没有数字?此外,在最后一个 if 语句中......如果输入是一个目录,我很难让它做我让它为文件做的同样的事情。它需要查找该目录中的所有文件,如果该目录中有另一个目录,则需要查找其中的所有文件,依此类推。然后它需要计算所有文件中每个单词的所有出现次数,并将它们存储到输出文件中,就像文件的情况一样。我正在考虑将它们存储在一个数组中,但我不确定它是否是最好的方法,而且我的语法是关闭的,因为它不起作用......所以我想知道我该怎么做?谢谢!

    #!/bin/bash

    INPUT="$1"
    OUTPUT="$2"
    ARRAY=();

    # Check that there are two arguments
    if [ "$#" -ne 2 ]
    then
       echo "Usage: $0 {dir-name}";
       exit 1
    fi

    # Check that INPUT is different from OUTPUT
    if [ "$INPUT" = "$OUTPUT" ]
    then
       echo "$INPUT must be different from $OUTPUT";
    fi

    # Check if INPUT is a file...if so, find number of occurrences of each word
    # and store in OUTPUT file sorted in greatest to least
    if [ -f "$INPUT" ]
    then
       for name in $INPUT; do
          if [ -f "$name" ]
          then
             xargs grep -hoP '\b\w+\b' < "$name" | sort | uniq -c | sort -n -r > "$OUTPUT"
          fi
       done
    # If INPUT is a directory, find number of occurrences of each word
    # and store in OUTPUT file sorted in greatest to least
    elif [ -d "$INPUT" ]
    then
       find $name -type f > "${ARRAY[@]}"
       for name in "${ARRAY[@]}"; do
          if [ -f "$name" ]
          then
             xargs grep -hoP '\b\w+\b' < "$name" | sort | uniq -c | sort -n -r > "$OUTPUT"
          fi
       done
    fi

【问题讨论】:

  • 您能否展示您的输入文件、预期输入和预期输出的示例。例如不清楚for name in $INPUT 应该做什么......因为$INPUT 应该是一个论点?
  • 你在做词频分析吗?你可能想先转换为小写,接受- 和其他一些东西。只是一个想法。你是用普通字母还是有特殊字符?
  • "我怎样才能让它只找到所有出现的有效单词而没有数字?"使用grep -hoP '\b[[:alpha:]]+\b' 代替grep -hoP '\b\w+\b'
  • @BroSlow 输入可以是任何类型的文件或目录。预期输出:17 字。旁边有单词的出现次数列表。 name in $INPUT 是输入中的每个文件名。

标签: bash


【解决方案1】:

我不建议您指定输出文件,因为您必须对其进行更多的有效性检查,例如

  • 输出不应存在(如果您不想允许覆盖)
  • 如果你想允许覆盖,如果输出存在,​​它必须是一个普通文件
  • 等等..
  • 最好有可能使用更多的输入目录/文件作为参数

因此更好(它更 bash-ish)产生输出到标准输出,您可以在调用时将其重定向到文件,例如

bash wordcounter.sh files or directories more the one to count words > to_some_file

例如

bash worcounter.sh some_dir >result.txt
#or
bash wordcounter.sh file1.txt file2.txt .... fileN.txt > result2.txt
#or
bash wordcounter.sh dir1 file1 dir2 file2 >result2.txt

整个wordcounter.sh 可能是下一个:

for arg
do
    find "$arg" -type f -print0
done |xargs -0 grep -hoP '\b[[:alpha:]]+\b' |sort |uniq -c |sort -nr

地点:

  • find 将在普通文件中搜索所有参数
  • 并在生成的文件列表上运行计数脚本

脚本窗台有一些缺点,例如也会尝试计算图像文件中的单词并喜欢,也许在下一个问题in this serie你会问它;)

编辑

如果你真的想要两个参数脚本,例如script where_to_search output(不太像 bash),将上面的脚本放入函数中,然后做任何你想做的事情,例如:

#!/bin/bash

wordcounter() {
    for arg
    do
        find "$arg" -type f -print0
    done |xargs -0 grep -hoP '\b[[:alpha:]]+\b' |sort |uniq -c |sort -nr
}

where="$1"
output="$2"
#do here the necessary checks
#...
#and run the function
wordcounter "$where" > "$output"
#end of script

【讨论】:

  • 我相信我需要根据我的理解指定输出文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多