Count number of lines after wrapped by terminal’s length [closed]

爷,独闯天下 提交于 2019-12-02 17:02:18

问题


Suppose your tput cols (or COLUMNS) is equal to 100 and you have a plain text file foo.txt with a single line that is 120 characters long.

If you wanted to count number of lines it contains you could do cat foo.txt | wc -l and unsurprisingly enough the output would presumably be 1.

But if you’d open the file with a pager, such as less, like less foo.txt then what your eyes would actually see are two lines instead (AFAIK, unless you don’t say --chop-long-lines, less will “wrap" lines that are longer than your terminal’s width).

Again, if you’d try to see line numbers, using less, like less --LINE-NUMBERS foo.txt, than the output would be something like:

1 something something...
1 more stuff

Basically less is “aware” that the only line in foo.txt is longer than your terminal’s width, so it will “wrap” it to visualize, but will tell you that actually first and the second lines that you see are actually the same line #1 in foo.txt.

So, my question is: how could you “calculate” (say, in bash) number of lines after wrapping (number of lines that your eyes see), rather than number of lines that the file actually contains? (In scenario above, the number would be 2 instead of 1.)


回答1:


Actually, there is a better solution:

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

The fold command will wrap a file to a given column count and is widely available as part of the GNU coreutils.




回答2:


This solution will print the number of lines as displayed on the terminal:

#!/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"



回答3:


Note: $COLUMNS is built in to bash and returns the current number of columns available for display.

We need to count the number of lines above our $COLUMN limit. We can do this with grep:

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

If we add this number to cat foo.txt | wc -l we get the number of lines after wrapping.

Script:

#!/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"

Note: line 2 eval $( resize ) is needed to make the $COULMNS variable available from within the script.

Hope this does the trick for you!


Just for kicks, here is how you could find the minimum possible lines after wrapping (assuming no line breaks).

characters="$(cat foo.txt | wc -c)"
minimum_possible_lines_after_wrapping="$(echo $COLUMNS | xargs echo "$characters / " | bc)"
  1. cat the file
  2. count the characters
  3. divide the number of characters by the maximum possible on each line

This only gets us the minimum possible number of lines, however.



来源:https://stackoverflow.com/questions/29996142/count-number-of-lines-after-wrapped-by-terminal-s-length

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!