1

I am using the following command:

 head -36 file.txt > file1.txt

where the file is 39 lines , but the thing is i'm checking that the file is 39 lines and so place the number 36 in the comment. So is there a way that the command calculates the number of lines and deduct the last 3 lines ?

t28292
  • 573
  • 2
  • 7
  • 12
  • It might help you more if you ask what you are REALLY trying to achieve i.e. what is wrong with the last 3 lines in your file – Adrian Aug 15 '13 at 16:39
  • simply that file is my input file , so sometimes i need the last 3 lines , sometimes i don't – t28292 Aug 15 '13 at 16:44
  • none of the answers worked ? do you have other suggestions? – t28292 Aug 16 '13 at 11:29

6 Answers6

3
awk -v nr=$(wc -l <file) 'NR<(nr-2)' file
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
2
nl=`wc -l file.txt | awk 's=$1-3{print s}'`; head -n $nl file.txt

wc -l calculates the total number of lines. Using awk, you can print the total number of lines -3. Then use head to read only that many lines...

iamauser
  • 11,119
  • 5
  • 34
  • 52
1

And here is awk only solution (no process substitution, piping, etc.)

awk 'NR==FNR{k++;next}FNR<=k-3' file.txt file.txt

Explanation:

  • We add the file.txt two times, so that awk reads it twice. The first time it counts the total number of lines in the file, and the second time it prints all the lines, except the last three
  • NR==FNR{k++;next}: The NR variable is the record number (including both filee), and the FNR is the record number in the current file. They are equal only for the records in the first file. So, for the first file we count the lines in it, with k++, and then we skip the remaining commands with next.
  • FNR<=k-3 If the FNR variable is smaller that the total lines in the file (which we counted in the previous bullet) - 3, then expression evaluates to true, and the line is printed. Otherwise, the expression evaluates to false (for the last three lines), and the line is not printed. This only happens for the second file, because of the next command in the previous block.
user000001
  • 32,226
  • 12
  • 81
  • 108
  • never use the letter `l` (el) as a variable name as it looks far too much like the number `1` (one). I once spent 3 hours staring at and debugging a syntax error in someone else's script because she'd learned in typing class that it was faster to type `1` than `l` (or vice-versa) and so had used that in a program - lesson learned... – Ed Morton Aug 15 '13 at 17:22
  • 1
    @EdMorton Good point. I had l for "line", but k is just as good. Congrads on reaching 10K by the way :) – user000001 Aug 15 '13 at 17:23
  • why do we have two file.txt ? – t28292 Aug 16 '13 at 11:11
  • the above comment doesn't display any output – t28292 Aug 16 '13 at 11:17
  • @user2613272 I have file.txt because awk will read it two times. The first time to count how many lines there are in total, and the second time to actually display the lines. I tested the above on my machine and it works. Did you add the file.txt two times? – user000001 Aug 16 '13 at 11:48
  • 1
    okay it worked perfectly ; can you please explain the syntax in detail just to make sure that i get it perfectly – t28292 Aug 17 '13 at 09:39
  • @user2613272 added an explanation. – user000001 Aug 17 '13 at 11:32
0

Hey you want to tell it how many lines to exclude, not how many you will end up with.

Also add the -n to check for an empty file.

head -n -3 file.txt


If not try with a temp file
head -n -3 file.txt > temp.txt ; mv temp.txt file.txt
iRector
  • 1,935
  • 4
  • 22
  • 30
0

Here's a pure awk based solution without using wc, head, tail, or any tracking arrays

  • Finished a 1.85 GB file in 2.456 seconds

Might be a tiny tiny bit slower than wc -l method, but this one works for items coming through the pipe as well as files with blank lines in between.

So as long as your data input is smaller than, say, 2.5 GB, might as well do it in one shot instead of the "idiomatic way"

 __="${m3t}"
 pvE0 < "$__" | wc5

 sleep 2

 ( time ( pvE0 < "$__" | 

   mawk2 'BEGIN { FS = OFS = RS
                             RS = "^$" 
                     _+=_^= ORS =  "" 

         } _^_ <= NF && NF -= _^("" == $NF)+_' 

 ) | pvE9 ) | wc5

 sleep 2

 ( time ( pvE0 < "$__" | mawk2 '…' ) | pvE9 ) | xxh128sum

      in0: 1.85GiB 0:00:13 [ 143MiB/s] [ 143MiB/s][===========>] 100%
        
rows = 12494275. | UTF8 chars = 1285316715. | bytes = 1983544693.


      in0:  322MiB 0:00:00 [3.15GiB/s] [3.15GiB/s] [====> ] 17% ETA 0:00:00
     out9: 1.85GiB 0:00:15 [ 125MiB/s] [ 125MiB/s] [ <=>               ]
      in0: 1.85GiB 0:00:00 [3.26GiB/s] [3.26GiB/s] [============>] 100%            
( pvE 0.1 in0 < "$__" | mawk2 ; )
       0.71s user 1.48s system 14% cpu 15.032 total

rows = 12494272. | UTF8 chars = 1285314823. | bytes = 1983539445.


      in0:  330MiB 0:00:00 [3.23GiB/s] [3.23GiB/s] [====> ] 17% ETA 0:00:00
     out9: 1.85GiB 0:00:02 [ 774MiB/s] [ 774MiB/s] [ <=> ]
      in0: 1.85GiB 0:00:00 [3.23GiB/s] [3.23GiB/s] [=========>] 100%  
      
( pvE 0.1 in0 < "$__" | mawk2 ; )

 0.71s user 1.46s system 88% cpu 2.456 total

45f50e894dae5cefcf3acc47fc402219  stdin
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11
-1

This should work

head -n -3 file.txt

From man head

 -n, --lines=[-]K
          print the first K lines instead of the first 10; with the leading '-', print all but the last K lines of each file
Vivek
  • 2,000
  • 3
  • 16
  • 22
  • Doesn't work on BSD - probably Linux-only - not sure about Solaris ? – Paul R Aug 15 '13 at 16:22
  • This doesn't answer the question. OP wants to deduct 3 lines from the total number of lines in the file NOT read 3 lines from the top... – iamauser Aug 15 '13 at 16:29
  • 1
    @iamuser please read the man page. With the leading - as in `-3` , head prints all but the last 3 lines, isn't that the same as deducting the last 3 lines. – Vivek Aug 15 '13 at 16:33
  • head in linux is part of gnu coreutils. It seems Solaris also uses gnu coreutils - http://www.opencsw.org/package/coreutils/ . I think it should work on solaris at least. I don't have a solaris system to confirm. – Vivek Aug 15 '13 at 16:41