Using awk
The method for multiple file input (see end of post) is the most robust.
Single file input:
awk 'BEGIN { printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt
The BEGIN
section runs before the input file is processed.
ARGV[1]
is the name of the input file. This corresponds to awk's FILENAME
variable, which does not work in the BEGIN
section.
!NF
matches lines that are blank or that only contain field separators. The default field separators are space and tab characters, so lines that contain only spaces and tabs count as empty. NF
(without the exclamation point) matches lines that contain data, and adding !
inverts the match.
NR
is the input file's line number currently being evaluated. NR
does not reset to 1 if additional input files are specified on the command line.
To prevent a comma from appearing in front of the first matching line number, leave the string sep
undefined until after printing the first match.
The END
section runs after the input file is processed. In this example, it terminates the output cleanly by printing a Unix-style newline character.
Example output:
Line numbers of empty lines in file.txt: 8,13,15,20,25,28
It's a bit sloppy to use a string name without first setting it, even if you initially want it to be empty. You could explicitly set the sep
string to be empty in the BEGIN
section:
awk 'BEGIN { sep="" ; printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt
Multiple file input:
awk 'FNR==1 && NR>1 { printf "\n" } FNR==1 { sep="" ; printf "Line numbers of empty lines in " FILENAME ": " } !NF { printf sep FNR ; sep="," } END { printf "\n" }' file1.txt file2.txt file3.txt
FNR
is similar to NR
, except that the FNR
line number counter resets to 1 at the start of each file.
The section FNR==1 && NR>1 { printf "\n" }
causes each file's output to print on a separate line. It prints a newline character when the first line of each additional input file is processed, but not for the first line of the first file.
Example output:
Line numbers of empty lines in file1.txt: 8,13,15,20,25,28
Line numbers of empty lines in file2.txt: 1,2,4,6,7,9,10
Line numbers of empty lines in file3.txt: 3,8,9,11,13,15
sed -i '/^$/d' file
will delete empty lines fromfile
. It might be a better solution to just print line numbers...