如何保留数字以便以后对其进行排序?

时间:2015-03-21 16:12:02

标签: linux bash shell vi

我有一个问题听起来像这样:编写一个shell脚本,从命令行为每个文件输出 比从键盘读取的数字k长的单词数。 输出必须按字数排序。

如何保留每个文件的字符数,以便对它们进行排序?

我尝试过类似的东西:

#!/bin/bash
if [ #@ -ne 1 ]
        then exit 1
fi
array[$@]=''
echo -n "Give the number>"
read k
for f in $@;
do
        n=`$f | wc -c`
        if [ $n -gt $k ];
        then
                i++
                array[i]=$n
        fi
done
echo {array[@]} | sort -n

2 个答案:

答案 0 :(得分:2)

挑战是:

  • 编写一个shell脚本,对于命令行中的每个文件,将输出比从键盘读取的数字k长的单词数。输出必须按字数排序。

我拒绝回答提示 - 命令接受参数。我和William Pursell建议说这个号码是第一个参数 - 这是一个合理的解决方案。另一种方法是使用-l 23之类的选项作为长度(以及调整其他操作的其他选项)。

到目前为止我看到的解决方案是计算单词的数量,而不是长于给定长度的单词数。这是个问题。为此,我认为awk是恰当的:

awk -v min=$k '{ for (i = 1; i <= NF; i++) if (length($i) >= min) print $i; }'

这会在标准输出上每行生成至少min个字符。我们一次只做一个文件,至少在第一次传递中。

然后,我们可以使用wc -l计算此类字词的数量。最后,我们可以用数字对数据进行排序。

将所有这些放在一起产生:

#!/bin/bash

case "$#" in
0|1) echo "Usage: $0 length file ..." >&2; exit 1;;
esac

k=${1:?"Cannot provide an empty length"}
shift

for file in "$@"
do
    echo "$(awk -v min=$k '{ for (i = 1; i <= NF; i++)
                                 if (length($i) >= min) print $i
                           }' "$file" |
            wc -l) $file"
done | sort -n

列出最后一个字长的文件;这很方便,因为最有趣的文件位于列表的末尾。如果您想要高数字,请将-r添加到sort

当然,如果我们使用awk,我们可以改善一些事情。它可以计算每个文件中长字的数量,并打印文件名和数字,因此对所有文件只需调用awk。不过,它需要更多的编程:

#!/bin/sh

case "$#" in
0|1) echo "Usage: $0 length file ..." >&2; exit 1;;
esac

k=${1:?"Cannot provide an empty length"}
shift

awk -v min=$k '
    FILENAME != oldfile { if (oldfile != "") { print longwords, oldfile }
                          oldfile = FILENAME; longwords = 0
                        }
    { for (i = 1; i <= NF; i++) if (length($i) >= min) longwords++ }
    END { if (oldfile != "") { print longwords, oldfile } }
    ' "$@" |
sort -n

如果你有GNU awk,甚至可以对awk内置的结果进行排序。

答案 1 :(得分:1)

您可以稍微简化脚本:

#!/bin/bash
(( $# > 0 )) || exit
read -r -p 'Enter number > ' k
wc -w "$@" | sed '$d' | gawk -v k="$k" '$1>k{print $0}' | sort -nr

,其中

  • read -r -p ...提示并阅读输入
  • wc -w - 计算您作为参数输入的所有文件的字数
  • sed ... - 跳过最后一行(total...)
  • awk会跳过count小于$k
  • 的行
  • sort - 用于排序输出

在@Tom Fench here的帮助下,它可以简化为:

wc -w "$@" | awk -v k="$k" 'NR>1&&p>k{print p}{p=$1}' | sort -nr

或使用文件名(基于@ Wintermute的评论here

wc -w "$@" | awk -v k="$k" 'p { print p; p="" } $1 > k { p = $0 }' | sort -nr

修改

根据@Jonathan Leffler的评论添加一个变体,用于计算每个文件中数字k更长的单词。

#!/bin/bash
(( $# > 0 )) || exit
read -r -p 'Enter number > ' k
let k++
grep -HoP "\b\w{${k:-3},}\b" "$@" |\
 awk -F: '{f[$1]++}END{for(n in f)print f[n],n}' |\
 sort -nr

其中:

  • grep...搜索输入数字更长的单词(如果希望等于,则省略let行)。打印出如下行:
file1:word1
file1:word2
...
file2:wordx
file2:wordy
  • 并且awk基于第一场计算频率,例如按文件名计算。