Use of cut to display information from last command linux - linux

I am trying to fetch the user name and IP from where they logged in on my system.
I used the following command:
last -i | grep 'Jan 12' | cut -f1,3
But I am getting full line as the result.
But when I use awk :
last -i | grep 'Jan 12' | awk '{print $1, $3}'
I am getting the correct result.
Why wrong output in case of cut command ?
Any help would be highly appreciated.

Default delimiter of cut is a tab, whereas default input field separator in awk is any whitespace i.e. space or tab.
To get the same behavior in cut, you need to add -d ' ' in cut to make it:
last -i | grep 'Jan 12' | tr -s ' ' | cut -d ' ' -f1,3
tr -s ' ' is required to squeeze multiple spaces into a single space.
However using awk lets you skip grep altogether and use:
last -i | awk '/Jan 12/{print $1, $3}'

In cut, default delimiter is [Tab]. Also with -d key you can specify only a single character as delimiter.
In last output there are 8 spaces in a row.
So, the best way is to use awk as in your example.
Bad, but working solution with cut:
last | grep 'Jun 23' | sed 's/\s\s*/ /g' | cut -d' ' -f1,3

Related

How to extract the date time from a string using bash

I have the below strings and from those i need to extract the data and time. I were trying to get these using awk command i am unable to find our the solution. The below lined are the put put of
grep -ir 'can not save data' Aplication-aplicationName-server0046704* | awk -F' GMT' '{print$1}' | grep -v 'can not save data'
Aplication-aplicationName-server0046704.log.1:2020 May 27 10:23:16:147
Aplication-aplicationName-server0046704.log.bkp:2020 May 27 10:23:16:147
desired output :
2020 May 27 10:23:16:147
Using sed:
sed -E 's/^[^:]+://' | uniq
Explanation:
The sed command will remove everything before the first :
and the first :
The uniq command will remove every duplicate
Using cut:
cut -d ':' -f2- | uniq
Explanation:
cut will accept as delimeter a : (-d ':') and will print the fields
from the second to the end (-f2-)
The uniq command will remove every duplicate

Sed, Awk for combining the output of two cut statements

I'm trying to combine the below outputs into one command. The issue is that the field I'm trying to grab is in reverse order. I was told that cut doesn't support a "reverse" option and to use AWK for this purpose but it didn't end up working for my purpose. I'm trying to take the output of the ls- l against the /dev/block to return the partitions and automatically build a dd if= / of= for each outputted line based on the output of the command.
I tried piping the output to awk:
cut -d' ' -f23,25 ... | awk '{print $2,$1}'
however, the result was when using sed to input the prefix and suffix, it wasn't in the appropriate order.
I built the two statements below which individually return the expected output, just looking for the "right" way to combine both of these statements in the most efficient manner using sed / awk.
ls -l /dev/block/platform/msm_sdcc.1/by-name/ | cut -d' ' -f 25 | sed "s/^/dd if=/"
ls -l /dev/block/platform/msm_sdcc.1/by-name/ | cut -d' ' -f 23 | sed "s/.*/of=\/external_sd\/&.dsk/"
Any assistance will be appreciated.
Thank you.
If you're already using awk, I don't think you'll need cut or sed. You can probably do something like the following, though I'll have to trust you on the field numbers
ls -l /dev/block/platform/msm_sdcc.1/by-name | awk '{print "dd if=/"$25 " of=/" $23 ".dsk"}'
awk will split on all whitespace, not just the space character, so it's possible the fields will shift some, though it may be more reliable too.

Bash grep output filename and line no without matches

I need to get a list of matches with grep including filename and line number but without the match string
I know that grep -Hl will give only file names and grep -Hno will give filename with only matching string. But those not ideal for me. I need to get a list without match but with line no. For this grep -Hln doesn't work. I tried with grep -Hn 'pattern' | cut -d " " -f 1 But it doesn't cut the filename and line no properly.
awk can do that in single command:
awk '/pattern/ {print FILENAME ":" NR}' *.txt
You were pointing it well with cut, only that you need the : field separator. Also, I think you need the first and second group. Hence, use:
grep -Hn 'pattern' files* | cut -d: -f1,2
Sample
$ grep -Hn a a*
a:3:are
a:10:bar
a:11:that
a23:1:hiya
$ grep -Hn a a* | cut -d: -f1,2
a:3
a:10
a:11
a23:1
I guess you want this, just line numbers:
grep -nh PATTERN /path/to/file | cut -d: -f1
example output:
12
23
234
...
Unfortunately you'll need to use cut here. There is no way to do it with pure grep.
Try
grep -RHn Studio 'pattern' | awk -F: '{print $1 , ":", $2}'

Keep only second attribute from each line

I have a csv file with 4 attributes in each line, delimited by comma. I'm trying to come up with a sed command to keep only the second attribute from each line. Any ideas on how to do it?
You'd be better off with cut:
cut -d "," -f 2 file.txt
If you want to remove dupes, and you don't mind the order of the entries, simply do:
cut -d "," -f 2 file.txt | sort -u
And to extend to attrs 1 and to, simply use:
cut -d "," -f 1,2 file.txt | sort -u
You do not need sed for this . The fastest is with cut:
cut -d, -f2 file
However , if you want sed , you can do it so:
sed '/[^,]*,\([^,]*\).*/ sxx\1x' file

How to extract version from a single command line in linux?

I have a product which has a command called db2level whose output is given below
I need to extract 8.1.1.64 out of it, so far i came up with,
db2level | grep "DB2 v" | awk '{print$5}'
which gave me an output v8.1.1.64",
Please help me to fetch 8.1.1.64. Thanks
grep is enough to do that:
db2level| grep -oP '(?<="DB2 v)[\d.]+(?=", )'
Just with awk:
db2level | awk -F '"' '$2 ~ /^DB2 v/ {print substr($2,6)}'
db2level | grep "DB2 v" | awk '{print$5}' | sed 's/[^0-9\.]//g'
remove all but numbers and dot
sed is your friend for general extraction tasks:
db2level | sed -n -e 's/.*tokens are "DB2 v\([0-9.]*\)".*/\1/p'
The sed line does print no lines (the -n) but those where a replacement with the given regexp can happen. The .* at the beginning and the end of the line ensure that the whole line is matched.
Try grep with -o option:
db2level | grep -E -o "[0-9]+\.[0-9]+\.[0-9]\+[0-9]+"
Another sed solution
db2level | sed -n -e '/v[0-9]/{s/.*DB2 v//;s/".*//;p}'
This one desn't rely on the number being in a particular format, just in a particular place in the output.
db2level | grep -o "v[0-9.]*" | tr -d v
Try s.th. like db2level | grep "DB2 v" | cut -d'"' -f2 | cut -d'v' -f2
cut splits the input in parts, seperated by delimiter -d and outputs field number -f

Resources