I have a script which returns few lines of output and I am trying to print the last two words of the last line (irrespective of number of lines in the output)
$ ./test.sh
service is running..
check are getting done
status is now open..
the test is passed
I tried running as below but it prints last word of each line.
$ ./test.sh | awk '{ print $NF }'
running..
done
open..
passed
how do I print the last two words "is passed" using awk or sed?
Just say:
awk 'END {print $(NF-1), $NF}'
"normal" awks store the last line (but not all of them!), so that it is still accessible by the time you reach the END block.
Then, it is a matter of printing the penultimate and the last one. This can be done using the NF-1 and NF trick.
For robustness if your last line can only contain 1 field and your awk doesn't retain the field values in the END section:
awk '{split($0,a)} END{print (NF>1?a[NF-1]OFS:"") a[NF]}'
This might work for you (GNU sed):
sed '$s/.*\(\<..*\<.*\)/\1/p;d' file
This deletes all lines in the file but on the last line it replaces all words by the last two words and prints them if successful.
Related
I am running Ubuntu Linux. I am in need to print filenames & line numbers containing more than 7 columns. There are several hundred thousand files.
I am able to print the number of columns per file using awk. However the output I am after is something like
file1.csv-463 which is to suggest file1.csv has more than 7 records on line 463. I am using awk command awk -F"," '{print NF}' * to print the number of fields across all files.
Please could I request help?
If you have GNU awk with you, try following code then. This will simply check condition if NF is greater than 7 then it will print that particular file's file name along with line number and nextfile will take program to next Input_file which will save our time because we need not to read whole Input_file then.
awk -F',' 'NF>7{print FILENAME,FNR;nextfile}' *.csv
Above will print only very first match of condition to get/print all matched lines try following then:
awk -F',' 'NF>7{print FILENAME,FNR}' *.csv
This might work for you (GNU sed):
sed -Ens 's/\S+/&/8;T;F;=;p' *.csv | paste - - -
If there is no eighth column, break.
Output the file name F, the line number = and print the current line p.
Feed the output into a paste command which prints three lines as one.
N.B. The -s option resets the line numbers for each file, without it, it will number each line for the entire input.
awk command to compare lines in file and print only first line if there are some new words in other lines.
For example: file.txt is having
i am going
i am going today
i am going with my friend
output should be
I am going
this will work for the sample input but perhaps will fail for the actual one, unless you have a representative input we wouldn't know...
$ awk 'NR>1 && $0~p {if(!f) print p; f=1; next} {p=$0; f=0}' file
i am going
you may want play with p=$0 to restrict matching number of fields if the line lengths are not in increasing order...
I have a very big text file. I want to merge the next line into the current line if the current line has a word OR in the end.
Eg. Like in the lines below
somerandomstring OR
someotherrandomstring
The above 2 lines should become
somerandomstring OR someotherrandomstring
Only those lines should change. Rest of the lines must be kept as they are. Thanks in advance.
Allow me to extend the question a bit further.
I want to also see if the next line starts with OR and the OR is not in the end of the current line, then how to achieve the above case and this case together?
With GNU sed:
sed '/ OR$/{N;s/\n/ /}' file
Search white space followed byOR at end of line ($) and if found then read next line (N) to pattern space and replace newline in pattern space (with s///) by one white space.
If you want to edit your file "in place" use sed's option -i.
You can do this in awk by assigning the "OR" row to a variable and printing whatever is stored in the variable when there is no "OR" found.
awk '$NF=="OR"{buffer=buffer$0" "} $NF!="OR"{print buffer$0;buffer=""}' test.txt
This also works on multiple rows that may have "OR" by concatenating the row to the buffer variable until it finds a non-OR row, prints it and clears the buffer variable.
Another option in awk is to use printf on the OR rows and print on the non-or rows (which is kind of similar to the GNU sed example by #cyrus, but in awk)
awk '$NF=="OR"{printf "%s ", $0} $NF!="OR"{print $0}' test.txt
And this is the same beast, but using a ternary operator within printf:
awk '{printf $NF=="OR"?"%s ":"%s\n", $0}' test.txt
another awk
$2$ awk -v RS='^$' -v k='OR' '{gsub(k ORS,k FS); gsub(ORS k,FS k); printf "%s",$0}' file
x OR y
x OR y
for test input file
$ cat file
x OR
y
x
OR y
Looking for a awk one liner for formatting some text in a file of this format where number of fields and number of lines are arbitrary:
abcd,abce,test1
bbcd,bbee,bbvc,test2
ccdd,ccbb,ccbd,ccab,testxyz
Where output is where the last field in each line is appended to each field in the line:
abcd,test1
abce,test1
bbcd,test2
bbee,test2
bbvc,test2
ccdd,testxyz
ccbb,testxyz
ccbd,testxyz
ccab,testxyz
Assuming all lines have at least 2 fields:
awk -F, '{OFS=","; for(i=1;i<NF;i++) print $i,$NF}' file
can do what you expect.
If there can be lines with just one field and you could just print it:
awk -F, '{OFS=","; for(i=1;i<NF;i++) print $i,$NF; if(NF==1) print $0}' file
This might work for you (GNU sed):
sed -r 's/,(.*(,[^,]*))$/\2\n\1/;P;D' file
If the line contains 2 or more commas, replace the first comma by a comma, the last field and a newline, print the first line, delete the first line and repeat.
I want AWK to process my file, and change only some lines. But it prints only rule-matched lines. So I've added a /*/ {print $0} rule. But then I've got a duplications.
awk '/rule 1/ {actions 1;} /*/ {print $0}' file.txt
I want all lines in the output, with 'rule 1' lines changed.
Adding a 1 to the end of the script, forces awk to return true, which has the effect of enabling printing of all lines by default. For example, the following will print all lines in the file. However, if the line contains the words rule 1, only the first field of that line will be printed.
awk '/rule 1/ { print $1; next }1' file
The word next skips processing the rest of the code for that particular line. You can apply whatever action you'd like. I just chose to print $1. HTH.
I'll make a big edit, following Ed Norton latest explanations.
as Ed Morton pointed out, it can even be simplified as : changing lines with specific patterns, and then printing all lines
awk '/regex1/ {actions_1} 1' file.txt
(see his comments below for the reason why it's preferable to the one I proposed)
For the record, there exist ways to skip the rest of the processing for the current line, such as : continue or break if it is in a loop, or next if it is in the main loop.
See for example : http://www.gnu.org/software/gawk/manual/html_node/Next-Statement.html#Next-Statement
Or assign the result of actions 1 to $0:
awk '/rule 1/{$0=actions 1}1' file.txt
for example:
awk '/rule 1/{$0=$1}1' file.txt