如何找到字符数最少的行

如何找到字符数最少的行

我正在编写一个 shell 脚本,使用任何通用的 UNIX 命令。我必须检索字符最少的行(包括空格)。最多可以有 20 行左右。

我知道我可以用来head -$L | tail -1 | wc -m查找 L 行的字符数。问题是,我能想到的唯一方法是手动编写一堆 if 语句,比较值。

示例数据:

seven/7
4for
8 eight?
five!

4for由于该行字符最少,因此将返回。

就我而言,如果多行的长度最短,则应返回单行。选择哪一个并不重要,只要它是最小长度即可。但我不认为向其他情况下的其他用户显示这两种方式有什么坏处。

答案1

awk这是打印第一个找到的最小行的解决方案的变体:

awk '
  NR==1 || length<len {len=length; line=$0}
  END {print line}
'

可以简单地通过一个条件扩展来打印所有最小行:

awk '
  length==len {line=line ORS $0}
  NR==1 || length<len {len=length; line=$0}
  END {print line}'
'

答案2

sqlite3

sqlite3 <<EOT
CREATE TABLE file(line);
.import "data.txt" file
SELECT line FROM file ORDER BY length(line) LIMIT 1;
EOT

答案3

一种 Perl 方式。请注意,如果有多行长度相同且最短的行,则此方法将仅打印其中一行:

perl -lne '$m//=$_; $m=$_ if length()<length($m); END{print $m if $.}' file 

解释

  • perl -lne:-n表示“逐行读取输入文件”,-l导致从每个输入行中删除尾随换行符,并在每个print调用中添加一个换行符;和-e是将应用于每一行的脚本。
  • $m//=$_:除非定义,否则设置$m为当前行 ( $_) 。$m//=运算符自 Perl 5.10.0 起可用。
  • $m=$_ if length()<length($m):如果当前值的长度$m大于当前行的长度,则将当前行($_)保存为$m
  • END{print $m if $.}:处理完所有行后,打印$m最短行的当前值。确保这仅在定义if $.行号 ( ) 时发生,避免为空白输入打印空行。$.

或者,由于您的文件足够小,可以容纳在内存中,因此您可以执行以下操作:

perl -e '@K=sort{length($a) <=> length($b)}<>; print "$K[0]"' file 

解释

  • @K=sort{length($a) <=> length($b)}<><>这是一个数组,其元素是文件的行。将sort根据它们的长度对它们进行排序,并将排序后的行保存为 array @K
  • print "$K[0]":打印数组的第一个元素@K:最短的行。

如果您想打印全部最短的线路,你可以使用

perl -e '@K=sort{length($a) <=> length($b)}<>; 
         print grep {length($_)==length($K[0])}@K; ' file 

答案4

我一直喜欢使用纯 shell 脚本的解决方案(无 exec!)。

#!/bin/bash
min=
is_empty_input="yes"

while IFS= read -r a; do
    if [ -z "$min" -a "$is_empty_input" = "yes" ] || [ "${#a}" -lt "${#min}" ]; then
        min="$a"
    fi
    is_empty_input="no"
done

if [ -n "$a" ]; then
    if [ "$is_empty_input" = "yes" ]; then
        min="$a"
        is_empty_input="no"
    else
        [ "${#a}" -lt "${#min}" ] && min="$a"
    fi
fi

[ "$is_empty_input" = "no" ] && printf '%s\n' "$min"

笔记:

输入中的 NUL 字节有问题。因此,printf "ab\0\0\ncd\n" | bash this_script打印ab而不是cd.

相关内容