计算终端长度包裹后的行数

Count number of lines after wrapped by terminal’s length

假设您的 tput cols(或 COLUMNS)等于 100,并且您有一个纯文本文件 foo.txt,单行长度为 120 个字符。

如果你想计算它包含的行数,你可以做 cat foo.txt | wc -l 不出所料,输出可能是 1.

但是如果你用寻呼机打开文件,比如 less,比如 less foo.txt 那么你的眼睛实际看到的是两行(AFAIK,除非你不说 --chop-long-linesless 将“换行”比终端宽度长的行。

同样,如果您尝试查看行号,使用 less,如 less --LINE-NUMBERS foo.txt,那么输出将类似于:

1 something something...
1 more stuff

基本上less“知道”foo.txt中唯一的一行比你终端的宽度长,所以它会“包装”它以可视化,但会先告诉你您看到的第二行实际上与 foo.txt.

中的第一行相同

所以,我的问题是:您如何“计算”(例如,在 bash 中) 换行后的行数(您的眼睛看到的行数),而不是文件实际包含的行数? (在上面的场景中,数字将是 2 而不是 1。)

此解决方案将打印终端上显示的行数:

#!/bin/bash

seenlines=0
cols=$( tput cols )

# iterate over each line in the file:
while read line
do

    # get length of the line in characters, 
    # subtracting the newline:
    length=$(( $( wc -m <<< "$line" ) - 1 ))

    # add at least one line, and one for each time
    # the line length exceeds the column size of 
    # the terminal, subtracting one character to 
    # avoid the edge case of length==cols:
    seenlines=$( bc <<< "$seenlines + 1 + (${length}-1)/ ${cols}" )
done <testfile

echo "${seenlines} lines seen"

注意:$COLUMNS 内置于 bash 和 returns 当前可显示的列数。

我们需要计算超出 $COLUMN 限制的行数。我们可以用 grep:

expression='.\{'"$COLUMNS"'\}'
echo $expression
.\{80\}
cat foo.txt | grep -c $expression
1

如果我们将此数字添加到 cat foo.txt | wc -l,我们将得到换行后的行数。

脚本:

#!/bin/bash
eval $(resize)
expression='.\{'"$COLUMNS"'\}'
echo $expression
raw_lines=`cat foo.txt | wc -l`
big_lines=`cat foo.txt | grep -c "$expression"`
display_lines=`echo "$big_lines + $raw_lines" | bc`
echo "raw lines: $raw_lines"
echo "big lines: $big_lines"
echo "display lines: $display_lines"

注意:需要第 2 eval $( resize ) 行才能使 $COULMNS 变量在脚本中可用。

希望这对你有用!


只是为了好玩,以下是您如何找到换行后可能的最少行数(假设没有换行符)。

characters="$(cat foo.txt | wc -c)"
minimum_possible_lines_after_wrapping="$(echo $COLUMNS | xargs echo "$characters / " | bc)"
  1. cat 文件
  2. 数字符数
  3. 将每行的字符数除以最大可能数

然而,这只会让我们得到尽可能少的行数。

其实还有更好的解决办法:

fold -w "$COLUMNS" testfile | wc -l

fold 命令会将文件包装到给定的列数,并且作为 GNU coreutils 的一部分广泛可用。