Unix cut operation - linux

I have a string like this:
uid=2560(jdihenia) gid=1000(undergrad)
I want to just get the undergrad part in to a variable name var1. So I used a command
var1=`echo "uid=2560(jdihenia) gid=1000(undergrad)" | cut -d "(" -f 3`
but this will assign the value undergrad) in to var1. Can you please tell me how can I get just the undergrad part in to the variable var1?

If you want the literal text "undergrad" in the brackets, this should work:
cut -d "(" -f 2 <text> | cut -d ")" -f 1
or equivalently
echo <text> | cut -d "(" -f 2 | cut -d ")" -f 1

If this string comes from id, then you can just call id -gn instead.

var1=$(cmd |sed 's/.*(\([^)]*\))/\1/')

var1="uid=2560(jdihenia) gid=1000(undergrad)"
var1=${var1#*\(*\(}
var1=${var1%%\)*}

echo "$str" | awk -F'[()]' '{print $4}'

var1=$( echo "uid=2560(jdihenia) gid=1000(undergrad)" | grep -Po 'gid=.*\(\K.*(?=\))')

Related

Strip a part of string in linux

Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 is my string and the result I want is vm-1.0.3
What is the best way to do this
Below is what I tried
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | awk -F - {'print $1,$2'}
vm 1.0.3
I also tried
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | awk -F - {'print $1"-",$2'}
vm- 1.0.3
Here I do not need space in between
I tried using cut and I got the expected result
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | cut -c 1-8
vm-1.0.3
What is the best way to do the same?
Making assumptions from the 1 example you provided about what the general form of your input will be so it can handle that robustly, using any sed:
$ echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' |
sed 's/^[^-]*-[^-]*-[^_]*_\(.*\)-[^-]*$/\1/'
vm-1.0.3
or any awk:
$ echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' |
awk 'sub(/^[^-]+-[^-]+-[^_]+_/,"") && sub(/-[^-]+$/,"")'
vm-1.0.3
You don't need 2 calls to awk, but your syntax with the single quotes outside the curly's, including printing the hyphen:
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 |
awk -F_ '{print $2}' | awk -F- '{print $1 "-" $2}'
If your string has the same format, let the field separator be either - or _
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F"[-_]" '{print $4 "-" $5}'
Or split the second field on - and print the first 2 parts
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F_ '{
split($2,a,"-")
print a[1] "-" a[2]
}'
Or with gnu-awk a bit more specific match with a capture group:
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 |
awk 'match($0, /^Apps-[^_]*_(vm-[0-9]+\.[0-9]+\.[0-9]+)/, a) {print a[1]}'
Output
vm-1.0.3
This is the easiest I can think of:
echo "Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2" | cut -c 25-32
Obviously you need to be sure about the location of your characters. In top of that, you seem to be have two separators: '_' and '-', while both characters also are part of the name of your entry.
echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' | sed -E 's/^.*_vm-([0-9]+).([0-9]+).([0-9]+)-.*/vm-\1.\2.\3/'

Converting date format in bash

I have similar different file of the format backup_2016-26-10_16-30-00 is it possible to rename using bash script to backup_26-10-2016_16:30:00 for all files.
Kindly suggest some method to fix this.
Original file:
backup_2016-30-10_12-00-00
Expected output:
backup_30-10-2016_12:00:00
To perform only the name transformation, you can use awk:
echo 'backup_2016-30-10_12-00-00' |
awk -F'[_-]' '{ print $1 "_" $3 "-" $4 "-" $2 "_" $5 ":" $6 ":" $7 }'
As fedorqui points out in a comment, awk's printf function may be tidier in this case:
echo 'backup_2016-30-10_12-00-00' |
awk -F'[_-]' '{ printf "%s_%s-%s-%s_%s:%s:%s\n", $1,$3,$4,$2,$5,$6,$7 }'
That said, your specific Linux distro may come with a rename tool that allows you to do the same while performing actual file renaming.
with perl based rename command:
$ touch backup_2016-30-10_12-00-00 backup_2016-26-10_16-30-00
$ rename -n 's/(\d{4})-([^_]+)_(\d+)-(\d+)-/$2-$1_$3:$4:/' backup*
rename(backup_2016-26-10_16-30-00, backup_26-10-2016_16:30:00)
rename(backup_2016-30-10_12-00-00, backup_30-10-2016_12:00:00)
remove the -n option for actual renaming
rename is for this task
$ rename 's/_(\d{4})-(\d\d-\d\d)_(\d\d)-(\d\d)-(\d\d)$/_$2-$1_$3:$4:$5/' backup_2016-30-10_12-00-00
but not sure will be simpler
you can also this script;
#!/bin/bash
fileName=$1
prefix=$(echo ${fileName} | cut -d _ -f1)
date=$(echo ${fileName} | cut -d _ -f2)
time=$(echo ${fileName} | cut -d _ -f3)
year=$(echo ${date} | cut -d - -f1)
day=$(echo ${date} | cut -d '-' -f2)
month=$(echo ${date} | cut -d '-' -f3)
formatedTime=$(echo $time | sed 's/-/:/g')
formatedDate=$day"-"$month"-"$year
formatedFileName=$prefix"_"$formatedDate"_"$formatedTime
echo $formatedFileName
Eg;
user#host:/tmp$ ./test.sh backup_2016-30-10_12-00-00
backup_30-10-2016_12:00:00

Count number of patterns with a single command

I'd like to count the number of occurrences in a string. For example, in this string :
'apache2|ntpd'
there are 2 different strings separated by | character.
Another example :
'apache2|ntpd|authd|freeradius'
In this case there are 4 different strings separated by | character.
Would you know a shell or perl command that could simply count this for me?
you can use awk command as below;
echo "apache2|ntpd" | awk -F'|' '{print NF}'
-F'|' is to field separator;
NF means Number of Fields
Example;
user#host:/tmp$ echo 'apache2|ntpd|authd|freeradius' | awk -F'|' '{print NF}'
4
you can also use this;
user#host:/tmp$ echo "apache2|ntpd" | tr '|' ' ' | wc -w
2
user#host:/tmp$ echo 'apache2|ntpd|authd|freeradius' | tr '|' ' ' | wc -w
4
tr '|' ' ' : translate | to space
wc -w : print the word counts
if there are spaces in the string, wc -w not correct result, so
echo 'apac he2|ntpd' | tr '|' '\n' | wc -l
user#host:/tmp$ echo 'apac he2|ntpd' | tr '|' ' ' | wc -w
3 --> not correct
user#host:/tmp$ echo 'apac he2|ntpd' | tr '|' '\n' | wc -l
2
tr '|' '\n' : translate | to newline
wc -l : number of lines
Do can do this just within bash without calling external languages like awk or external programs like grep and tr.
data='apache2|ntpd|authd|freeradius'
res=${data//[!|]/}
num_strings=$(( ${#res} + 1 ))
echo $num_strings
Let me explain.
res=${data//[!|]/} removes all characters that are not (that's the !) pipes (|).
${#res} gives the length of the resulting string.
num_strings=$(( ${#res} + 1 )) adds one to the number of pipes to get the number of fields.
It's that simple.
Another pure bash technique using positional-parameters
$ userString="apache2|ntpd|authd|freeradius"
$ printf "%s\n" $(IFS=\|; set -- $userString; printf "%s\n" "$#")
4
Thanks to cdarke's suggestion from the commands, the above command can directly store the count to a variable
$ printf -v count "%d" $(IFS=\|; set -- $userString; printf "%s\n" "$#")
$ printf "%d\n" "$count"
4
With wc and parameter expansion:
$ data='apache2|ntpd|authd|freeradius'
$ wc -w <<< ${data//|/ }
4
Using parameter expansion, all pipes are replaced with spaces. The result string is passed to wc -w for word count.
As #gniourf_gniourf mentionned, it works with what at first looks like process names but will fail if strings contain spaces.
You can do this with grep as well-
echo "apache2|ntpd|authd|freeradius" | grep -o "|" | wc -l
Output-
3
That output is the number of pipes.
To get the number of commands-
var=$(echo "apache2|ntpd|authd|freeradius" | grep -o "|" | wc -l)
echo $((var + 1))
Output -
4
You could use awk to count the occurrances of delimiters +1:
$ awk '{print gsub(/\|/,"")+1}' <(echo "apache2|ntpd|authd|freeradius")
4
may be this will help you.
IN="apache2|ntpd"
mails=$(echo $IN | tr "|" "\n")
for addr in $mails
do
echo "> [$addr]"
done

How get value from text file in linux

I have some file xxx.conf in text format. I have some text "disablelog = 1" in this file.
When I use
grep -r "disablelog" oscam.conf
output is
disablelog = 1
But i need only value 1.
Do you have some idea please?
one way is to use awk to print just the value
grep -r "disablelog" oscam.conf | awk '{print $3}'
you could also use sed to replace diablelog = with empty
grep -r 'disablelog' oscam.conf | sed -e 's/disablelog = //'
If you also want to get the lines with or without space before and after = use
grep -r 'disablelog' oscam.conf | sed 's/disablelog\s*=\s*//'
above command will also match
disablelog=1
Assuming you need it as a var in a script:
#!/bin/bash
DISABLELOG=$(awk -F= '/^.*disablelog/{gsub(/ /,"",$2);print $2}' /path/to/oscam.conf)
echo $DISABLELOG
When calling this script, the output should be 1.
Edit: No matter wether there is whitespace or not between the equals sign and the value, the above will handle that. The regex should be anchored in either way to improve performance.
Try:
grep -r "disablelog" oscam.conf | awk -F= '{print $2}'
Just for fun a solution without awk
grep -r disablelog | cut -d= -f2 | xargs
xargs is used here to trim the whitespace

Extract ID from the JSON Response in Linux

Here is my json response from the server.This response i am saving in a variable named TESTDEMO.
{
"objects":[
{
"meta":{
"type":"test-folder",
"#href":"{HOST_URL}/TsetRESTServices/objects/test-folder/0F071CE4-790D11E3-AAC0-005056A5408D",
"name":"demo"
},
"meta":{
"type":"test-folder",
"#href":"{HOST_URL}/TsetRESTServices/objects/test-folder/0F072CE4-190A11E3-AAC0-00AA56A5408K",
"name":"folder "
}
}]
}
Want to extract the id 0F071CE4-790D11E3-AAC0-005056A5408D of the folder "name":"demo".
Need Help.
Try this:
redirect your JSON to sed command and grep according to the name:demo.
echo $TESTDEMO | sed 's/{/\n{/g' | grep '"name":"demo"' | cut -d',' -f2 | cut -d'/' -f 7 | cut -d'}' -f 1 | cut -d '"' -f 1
Hope this will helpful.
Like this?
awk -F"[/\"]" '/"name":"demo"/ {print $5}' RS="}" <<< "$variable"
0F071CE4-790D11E3-AAC0-005056A5408D
sed -n '/"type":"test-folder"/,/"name":"demo"/ {s/[[:blank:]]*"#href":"{HOST_URL}//;s/",$//p}' <<< "$TESTDEMO"
take the block type to name and print line havin #href and finished by ', after removing them

Resources