Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'd like to find lines in my code which exceed a certain length. My code is in multiple files. What's a good way to do this?

I'd like to know the files and line numbers; content would be preferred, but not necessary. The purpose of the exercise is to then figure out how to break the lines (probably manually).

share|improve this question
    
How do you want the results? As the lines itself (their content, as in grep), or as line numbers, or as something else (perhaps you want to apply another action on them)? Probably the most convenietn way to do this depends on what will be done with these lines next. –  imz -- Ivan Zakharyaschev Mar 27 at 15:21
    
@imz--IvanZakharyaschev Good point. Question updated. –  Marcin Mar 27 at 16:01

7 Answers 7

up vote 10 down vote accepted

With grep:

grep -En '.{12}' file

For lines at least 12 characters long.

With several files:

find . -type f -exec grep -En '.{12}' {} +

Some grep implementations like GNU grep, can do the file-finding themselves.

grep -rEn '.{12}' .

But beware of symlinks and other non-regular files.

share|improve this answer
    
I like this because it's simple, and I was hoping to do something like this (still haven't gotten around to it). –  Marcin Mar 28 at 15:49

AWK solution

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

Or, more concisely:

awk 'length > 5' file
share|improve this answer
8  
We can shorten your version awk 'length > 5' –  Gnouc Mar 27 at 15:15
    
Gnouc is a brace killer ;) –  Ouki Mar 27 at 15:16
1  
+1 for awk 'length > 5' –  yeti Mar 27 at 15:23
3  
With GNU awk the somewhat less elegant but concise awk '/^.{6,}/' –  1_CR Mar 27 at 15:56
2  
@1_CR, That's POSIX and can be shortened to awk '/.{6}/' (actually GNU awk until recently used to be the one where that wouldn't work unless you pass POSIXLY_CORRECT to its environment). –  Stéphane Chazelas Mar 27 at 16:20

Since the one thing that was missing was a sed solution

sed -n '/^.\{6,\}/p' file
share|improve this answer

Bash solution

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

So, e.g., ./whatever.sh < input.file. This does not include the newline by subtracting 1 from $len; if that's not desirable, or your input uses CRLF endings, you should adjust accordingly.

share|improve this answer
1  
why not ${#line} to avoid the expr fork? –  1_CR Mar 27 at 15:36
1  
ha ha, +1 for the pure bash solution. But please note that unless you stick in IFS= in front of read, leading spaces will be ignored. –  1_CR Mar 27 at 15:43
1  
Added in a few bash good practices. Also please note the the newline is not taken into $line so no need to subtract one. –  1_CR Mar 27 at 17:40
2  
@1_CR actually if you don't give read a name to read into, it will read into REPLY and include all whitespace. No IFS setting needed. –  kojiro Mar 27 at 18:37
2  
That's going to be extremely slow and handles the backslash characters specially. while read loops to process text are really bad practice. –  Stéphane Chazelas Mar 27 at 20:32

With perl (for instance), assuming you are searching for lines longer than 80 characters:

To display the lines:

$ perl -nle 'print if length > 80' your_file

To display the lines number:

$ perl -nle 'print "$.\n" if length > 80' your_file

Or both:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file
share|improve this answer
3  
You should add -l command line, perl will count line break in your lines. –  Gnouc Mar 27 at 15:22

Ruby :

ruby -lne 'puts $_ if $_.size > 5' intputfile

Python :

python -c "import sys;[ sys.stdout.write(''.join(line)) for line in sys.stdin if len(line.strip()) > 5 ]" < inputfile
share|improve this answer

Here's another bash solution (bash 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

The resulting array is sparse, so the array indices are maintained. Since we started at 1, the indices are the line numbers of the lines we kept. We can output just those line numbers:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

Or we can output the lines themselves:

printf '%s\n' "${MAPFILE[@]}"
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.