Get first characters to a variable - variables

I have an output like this
I need to get the id 65a8fa6 as an variable to a new command.
I'm familiar with grep and use it to get the line I need. But how do I only pick the first 7 caracters.
This is where I'm now
vagrant global-status | grep DB1
Output
65a8fa6 default vmware_desktop running /Users/USER/Documents/Vagrant/centos7SN/DB1

1st solution: You could simply do this with awk. Simply look for string DB in line and then if its found then print 1st field of that line. Save the output into variable var and later you could use it for your use.
val=$(vagrant global-status | awk '/DB1/{print $1}')
OR for matching either db1 OR DB1 try in any awk:
val=$(vagrant global-status | awk '/[dD][bB]1/{print $1}')
2nd solution: If you have GNU awk and you want to use ignorecase then try:
val=$(vagrant global-status | awk -v IGNORECASE="1" '/DB1/{print $1}')
3rd solution: To get first 7 characters try:
But how do I only pick the first 7 characters.
val=$(vagrant global-status | awk '/[dD][bB]1/{print substr($0,1,7)}')

Sed alternative:
val=$(vagrant global-status | sed -rn 's/(^[[:alnum:]]{7})(.*$)/\1/p')
Split the output of vagrant ... into two sections using sed and regular expressions (-r) Substitute the line for the first section only and print.

You can also use the cut command to find instances of what you're after, provided that there's some consistent text near what you want to find:
Say you want to find Hello out of the following line:
Hello here's some text blablablabla
You can find it doing something like:
echo Hello here's some text blablablabla | grep text | cut -d " " -f 1
Should output Hello

Related

AWK print between two characters

When I try this command:
/usr/bin/curl -s sketch*.zip "https://www.sketch.com/downloads/mac/" |\
grep 'download.sketchapp.com/sketch-' | awk 'NR==1{print $3}'
The output is:
content="0;URL='https://download.sketchapp.com/sketch-68.2-102594.zip
what I am looking to get is:
68.2
Any help would be appreciated.
It seems you want to extract the number after your pattern, only for the first matcing row. You can use one grep command:
... | grep -oPm1 '(?<=download.sketchapp.com/sketch-)[^-]+' file
or as this is the 3rd field of your 1st curl output row you want, you can use one awk command (split field using hyphen as separator to array and print the element in the middle):
awk '/download.sketchapp.com/sketch-/ && NR==1 {split($3,a,"-"); print a[2]; exit}'
Using sed:
/usr/bin/curl -s sketch*.zip "https://www.sketch.com/downloads/mac/" | \
sed -n 's!.*download.sketchapp.com/sketch-\([^-]*\).*!\1!p;' | \
head -1
head is to get rid of multiple matches. sed command extracts non-hyphen characters after download.sketchapp.com/sketch-.

Awk/Sed: Replacing a specific character in a line by index (after getting the value from grep)

Below i have found the value to change in the file.
value_to_change=$(grep "$mbean" "$instr_file_path" | awk -F= '{print $2}' | awk -v awk_index="$index" '{print $awk_index}')
I want to do a sed on that line to replace the specific value at the specific place. Note that this may be a 0, 1 whatever so ill need to know where it is in the line to do the find and replace in that area only.
How do i go about this?
$ awk -v term="$mbean" -v index="$index" \
'$0~term{split($0,r,"=");
split(r[2],fields);
print fields[index]}' file
obviously not tested...
However, I guess this wasn't really your question. Do you want to replace the value at that index? With what other value?

awk to remove 5th column from N column with fixed delimiter

I have file with Nth columns
I want to remove the 5th column from last of Nth columns
Delimiter is "|"
I tested with simple example as shown below:
bash-3.2$ echo "1|2|3|4|5|6|7|8" | nawk -F\| '{print $(NF-4)}'
4
Expecting result:
1|2|3|5|6|7|8
How should I change my command to get the desired output?
If I understand you correctly, you want to use something like this:
sed -E 's/\|[^|]*((\|[^|]*){4})$/\1/'
This matches a pipe character \| followed by any number of non-pipe characters [^|]*, then captures 4 more of the same pattern ((\|[^|]*){4}). The $ at the end matches the end of the line. The first part of the match (i.e. the fifth field from the end) is dropped.
Testing it out:
$ sed -E 's/\|[^|]*((\|[^|]*){4})$/\1/' <<<"1|2|3|4|5|6|7"
1|2|4|5|6|7
You could achieve the same thing using GNU awk with gensub but I think that sed is the right tool for the job in this case.
If your version of sed doesn't support extended regex syntax with -E, you can modify it slightly:
sed 's/|[^|]*\(\(|[^|]*\)\{4\}\)$/\1/'
In basic mode, pipes are interpreted literally but parentheses for capture groups and curly brcneed to be escaped.
AWK is your friend :
Sample Input
A|B|C|D|E|F|G|H|I
A|B|C|D|E|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|D|O|R|Q|U|I
A|B|C|D|E|F|G|H|I|E|O|Q
A|B|C|D|E|F|G|H|I|X
A|B|C|D|E|F|G|H|I|J|K|L
Script
awk 'BEGIN{FS="|";OFS="|"}
{$(NF-5)="";sub(/\|\|/,"|");print}' file
Sample Output
A|B|C|E|F|G|H|I
A|B|C|D|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|O|R|Q|U|I
A|B|C|D|E|F|H|I|E|O|Q
A|B|C|D|F|G|H|I|X
A|B|C|D|E|F|H|I|J|K|L
What we did here
As you are aware awk's has special variables to store each field in the record, which ranges from $1,$2 upto $(NF)
To exclude the 5th from the last column is as simple as
Emptying the colume ie $(NF-5)=""
Removing from the record, the consecutive | formed by the above step ie do sub(/\|\|/,"|")
another alternative, using #sjsam's input file
$ rev file | cut -d'|' --complement -f6 | rev
A|B|C|E|F|G|H|I
A|B|C|D|F|G|H|I|A
A|B|C|D|E|F|G|H|I|F|E|O|R|Q|U|I
A|B|C|D|E|F|H|I|E|O|Q
A|B|C|D|F|G|H|I|X
A|B|C|D|E|F|H|I|J|K|L
not sure you want the 5'th from the last or 6th. But it's easy to adjust.
Thanks for the help and guidance.
Below is what I tested:
bash-3.2$ echo "1|2|3|4|5|6|7|8|9" | nawk 'BEGIN{FS="|";OFS="|"} {$(NF-4)="!";print}' | sed 's/|!//'
Output: 1|2|3|4|6|7|8|9
Further tested on the file that I have extracted from system and so it worked fine.

How to grep from within specified character range in line and then print entire line

I have a file which have multiple row each row contains 3400 characters. I want to grep something from specified character range, let's say I want to grep "pavan" between character range 14 to 25 in the line.
To do this I can simply do like below
cat filename | cut -c 14-25 | grep pavan
I tried to use awk command but it does not work since the lines have more than `3000 characters
but by this complete line will not print.
I want to print complete line also so that I can perform further operation on it.
awk -v pattern="pavan" 'match( substr($0, 14, 11), pattern )' file
Will print the matching lines.
A more complicated way of doing the same thing:
awk -v patt="pavan" -v start=14 -v end=25 '
match($0,patt) && start <= RSTART && RSTART <= end-RLENGTH
' file
-- stricken due to valid commentary from Ed Morton.
Some bit of arithmetic and you could use grep:
grep -E '^.{13}.{0,7}pavan' filename
This would match lines containing pavan between the specified character range.
It essentially matches 13 arbitrary characters at the beginning of a line. Then looks for pavan that can be preceded by 0 to 7 arbitrary characters.
This is not very elegant, but does work!
Start off with what you had, but remove the unnecessary cat:
cut -c 14-25 file
now get awk to find the string you want and print the line number:
cut -c 14-25 file | awk '/paven/{print NR}'
Now you have a list of all the line numbers that you want. You can either process them in a while loop, like this:
cut -c 14-25 file | awk '/pavan/{print NR}' | while read line; do
echo $line
sed -n "${line} p"
done
or put them in an array
lines=($(cut -c 14-25 file | awk '/pavan/{print NR}'))
echo ${lines[#]}

How to quote a shell variable in a TCL-expect string

I'm using the following awk command in an expect script to get the gateway for a particular destination
route | grep $dest | awk '{print $2}'
However the expect script does not like the $2 in the above statement.
Does anyone know of an alternative to awk to perform the same function as above? ie. output 2nd column.
You can use cut:
route | grep $dest | cut -d \ -f 2
That uses spaces as the field delimiter and pulls out the second field
To answer your Expect question, single quotes have no special meaning to the Tcl parser. You need to use braces to protect the body of the awk script:
route | grep $dest | awk {{print $2}}
And as awk can do what grep does, you can get away with one less process:
route | awk -v d=$dest {$0 ~ d {print $2}}
Before switching to another utility, check if changing field separator worrks. Documentation for field separators in GNU Awk here.
SED is the best alternative to use. If you don't mind a dependency, Perl should also be sufficient to solve the task
Depending on the structure of your data, you can use either cut, or use sed to do both filtering and printing the second column.
Alternatively, you could use Perl:
perl -ne 'if(/foo/) { #_ = split(/:/); print $_[1]; }'
This will print second token of each line containing foo, with : as token separator.