Bash - 从整数列表中获取最大值

10

这个脚本将cvs列表分成三列。我们关注“name”列。我想找出字符最多的名称。一旦我找到了字符最多的名称,我想将其分配给一个变量。

#!/bin/bash
for i in $(cat homeaway.txt )
do
echo $i | while IFS=, read -r area name host
do
        maxLength=0
        length=${#name}
        if [ $length -gt $maxLength ] ; then
            maxLength=$length
        else
           :
        fi
        printf "%s\n" $maxLength

      done
done

该脚本的意思是:如果长度大于最大长度(maxlength),则将长度设置为maxLength,否则不做任何操作。其中包含最多字符的区域字符串是“script_name_12345678999999”,它有26个字符。当脚本读取所有字符时,$maxLength应返回26。

__DATA__
HOME,script_name_12345,USAhost.com   
AWAY,script_name_123,USAhost.com
HOME,script_name_1,EUROhost.com
AWAY,script_name_123,USAhost.com
HOME,script_name_123456,EUROhost.com
AWAY,script_name_12345678999999,USAhost.com
HOME,script_name_1234,USAhost.com
AWAY,script_name_1234578,USAhost.com
HOME,script_name_12,EUROhost.com
AWAY,script_name_123456789,USAhost.com

一旦脚本到达26个字符的区域值,应停止将任何内容分配给$maxLength。 取而代之的是,它返回每个字符串长度的列表,我不知道为什么会出现零。
casper@casper01.com $ ./length_test.sh
17
0   ### how does the zero get in here ?
15
13
15
18
26  ###script_name_12345678999999
16
19
14
21

每次循环都是 maxLength=0 吗? - David C. Rankin
不打算在循环中将maxLength重置为零。我以为我只是在初始化它。 - capser
6个回答

28

my_command | sort -n | tail -1

将命令的输出按数字大小升序排序,获取排序后列表中的最后一个元素。


7
在GNU/Linux上,你也可以一次完成这个操作。如果文件data包含了你的记录:
cut --delimiter=, --fields=2 < data | wc --max-line-length

用中文:

  • 提取第二列,使用","作为字段分隔符
  • 打印最长行的长度

2
这是非常引人入胜的编程作品。 - capser
1
我认为这展示了 shell 的优雅和强大之处。 - capser
我认为我们想要从整数列表中找到最大值?如果所有值都有相同的数字位数,那么这种方法行不通,对吧? - User12547645
另外,我认为 wc -L 命令会输出最长行的长度。因此它只会给出最大数字的位数(例如,如果 400 是您的最大数字,则 wc -L 将给出 3)。 - User12547645
@User12547645 这个问题的意思是“我想找出名字中字符最多的那个。”因此是指字符数量最多,而不是数值最大。 - bishop
1
啊,好的。我关注的是“我想要在整数列表中找到最大的整数”。 - User12547645

3

你的循环有点奇怪(技术术语),并且你在每次迭代循环时将maxLength重置为零。你需要更像这样的东西:

#!/bin/bash

fn="${1:-/dev/stdin}"   ## read from file given as 1st argument (default stdin)

test -r "$fn" || {      ## validate file is readable 
    printf "error: file not readable '%s'.\n" "$fn"
    exit 1
}

declare -i maxlength=0  ## set maxlength before loop
maxname=

while IFS=, read -r area name host
do
    test -n "$name" || continue            ## if name not set get next line
    len=${#name}
    if [ "$len" -gt "$maxlength" ]; then   ## test length against max
        maxlength=$len                     ## update max if greater
        maxname="$name"                    ## save name in maxname
    fi
done <"$fn"                                ## feed loop by redirecting file

printf "maxname: %s  (len: %d)\n" "$maxname" "$maxlength"

示例用法/输出

$ bash maxnm.sh <dat/maxnm.txt
maxname: script_name_12345678999999  (len: 26)

请仔细查看并告诉我您是否有进一步的问题。

2

如果你能使用awk,这很容易

因为你说:

这个脚本将cvs列表分成三列。我们关注“名称”列。我想发现字符最多的名称

awk -F, '{l=length($2)}l>max{max=l; name=$2}END{print name, max}' infile

以下是测试结果:

$ cat infile
HOME,script_name_12345,USAhost.com   
AWAY,script_name_123,USAhost.com
HOME,script_name_1,EUROhost.com
AWAY,script_name_123,USAhost.com
HOME,script_name_123456,EUROhost.com
AWAY,script_name_12345678999999,USAhost.com
HOME,script_name_1234,USAhost.com
AWAY,script_name_1234578,USAhost.com
HOME,script_name_12,EUROhost.com
AWAY,script_name_123456789,USAhost.com

$ awk -F, '{l=length($2)}l>max{max=l; name=$2}END{print name, max}' infile
script_name_12345678999999 26

如果您只想将maxlength的script_name存储到变量中,那么只需打印变量名称,并将其包装在$(....)中,如下所示。
$ myvar=$( awk -F, '{l=length($2)}l>max{max=l; name=$2}END{print name}' infile )
$ echo "$myvar"
$ script_name_12345678999999

0

这里是另一种排序方法,使用数组:

declare    -a count
while read -r area name host; do
    count[${#name}]+=" $name" # if there are more then one equally big names
done < <(sed 's/,/ /g' data)

最后一个项目将是最大的:

$ for i in ${!count[@]}; { echo $i ${count[$i]}; }
13 script_name_1
14 script_name_12
15 script_name_123 script_name_123
16 script_name_1234
17 script_name_12345
18 script_name_123456
19 script_name_1234578
21 script_name_123456789
26 script_name_12345678999999

获取最后一个:
$ echo ${count[@]:(-1)}
script_name_12345678999999

0

在Bash中使用另一个max()

#!/usr/bin/env bash
set -u

# simple one liner returning max of two numbers
max2() { printf '%d' $(( $1 > $2 ? $1 : $2 )); }

# max of n numbers
max() {
  [[ $# > 0 ]] || {
    echo "Warning: max takes minimum one argument"
    return 1
  }

  local rs=0 # return status
  local max="$1"
  shift

  for n in "$@"; do
    max=$(( "$n" > "$max" ? "$n" : "$max" ))
    rs=$(( $? > $rs ? $? : $rs ))
  done

  printf '%d' $max
  return $(( $? > $rs ? $? : $rs ))
}

# max 4 5 2 -65 12 11
## output:12

str="4 15 2 -65 +17 11"
echo "max in '${str}' is $(max ${str% * })"
## output: max in '4 15 2 -65 +17 11' is 17

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接