get a part of string just like accessing an array? - shell

In shell,
s="abc\tdef\tghi" # 3 words separated by \t
What if I want to get the second word which is def?
PS
I know cut can do the job, but any way else just like variable substitution?

How about cut ?
[cnicutar#ariel ~]$ echo -e $s | cut -f2
def
Or maybe awk:
echo -e $s | awk '{print $2}'

Maybe you're looking for this.
s="abc\tdef\tghi"
s=${s#*\t}
s=${s%\\t*}
echo $s

Related

"awk" and "cut" behaving differently in bash script

I'm trying to cut the below string starting on the single quote:
name1=O'Reilly
so it leaves:
name2=Reilly
That's easy from the command line with the following commands:
echo $name | cut -d\' -f
echo $name | awk -F\' '{print $2}'
However when I run these commands from a script the string remains unaltered. I've been looking into problems with using single quotes as a delimiter but couldn't find anything. Any way to solve this issue?
That does not change the string the variable expands to, it just outputs the result of string manipulation.
If you want to create a new reference for variable name, use command substitution to save the result of cut/awk operation as variable name:
% name="O'Reilly"
% echo "$name" | awk -F\' '{print $2}'
Reilly
% name=$(echo "$name" | awk -F\' '{print $2}')
% echo "$name"
Reilly
On the other hand, if you want to declare the input as one (name1), and save the output as a different variable (name2):
% name1="O'Reilly"
% name2=$(echo "$name1" | awk -F\' '{print $2}')
% echo "$name2"
Reilly
This might be easier to get using Parameter expansion though:
$ name="O'Reilly"
$ echo "${name#*\'}"
Reilly
$ name="${name#*\'}"
$ echo "$name"
Reilly

Capitalize bash variable

I have the following line in bash:
echo "Manufacturer: $(echo ${family:-$name}|cut -d' ' -f1)"
I would like to capitalize the echoed string using the ${var^} syntax but not sure how to add this to the current line. Can someone please suggest how to do this?
two one liners
$ echo "watever" | awk '{print toupper($0)}'
$ echo "watever" | tr '[:lower:]' '[:upper:]'
Just store above command's output in a variable using command substitution:
s=$(echo "Manufacturer: $(echo ${family:-$name}|cut -d' ' -f1)")
and then use:
echo "${s^^}"
to capitalize the string.
sed is handy here:
name=smith
family=""
echo "Manufacturer: $(sed 's/[^[:blank:]]\+/\U&/' <<< "${family:-$name}")"
Manufacturer: SMITH
If you only want to "title-case" it ("Manufacturer: Smith"), use \u instead of \U

Split String in Unix Shell Script

I have a String like this
//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf
and want to get last part of
00000000957481f9-08d035805a5c94bf
Let's say you have
text="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"
If you know the position, i.e. in this case the 9th, you can go with
echo "$text" | cut -d'/' -f9
However, if this is dynamic and your want to split at "/", it's safer to go with:
echo "${text##*/}"
This removes everything from the beginning to the last occurrence of "/" and should be the shortest form to do it.
For more information on this see: Bash Reference manual
For more information on cut see: cut man page
The tool basename does exactly that:
$ basename //ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf
00000000957481f9-08d035805a5c94bf
I would use bash string function:
$ string="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"
$ echo "${string##*/}"
00000000957481f9-08d035805a5c94bf
But following are some other options:
$ awk -F'/' '$0=$NF' <<< "$string"
00000000957481f9-08d035805a5c94bf
$ sed 's#.*/##g' <<< "$string"
00000000957481f9-08d035805a5c94bf
Note: <<< is herestring notation. They do not create a subshell, however, they are NOT portable to POSIX sh (as implemented by shells such as ash or dash).
In case you want more than just the last part of the path,
you could do something like this:
echo $PWD | rev | cut -d'/' -f1-2 | rev
You can use this BASH regex:
s='//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf'
[[ "$s" =~ [^/]+$ ]] && echo "${BASH_REMATCH[0]}"
00000000957481f9-08d035805a5c94bf
This can be done easily in awk:
string="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"
echo "${string}" | awk -v FS="/" '{ print $NF }'
Use "/" as field separator and print the last field.
You can try this...
echo //ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf |awk -F "/" '{print $NF}'

Using values of variables in on-the-spot shell commands (using ``)

I have a shell script that for-loops over input to get a number and string. If I want to test the number in the loop, can I cut the looped-over variable to get the number? For example, something like:
for line in input
do
num=`cut -f1 $line`
...
done
If not, how else can I accomplish this?
Instead of:
num=`cut -f1 $line`
You can do:
num=$(echo "$line" | cut -f1)
OR else using awk:
num=$(awk '{print $1}' <<< $line)
OR using pure BASH:
num=${line%% *}
Your command cut -f1 $line will try to cut first column from a file named as $line.
Is this what you want instead ?
while read -r number str
do
echo $number;
echo $str;
done < input

Extract text from hostname

Using OS X, I need a one line bash script to look at a client mac hostname like:
12345-BA-PreSchool-LT.local
Where the first 5 digits are an asset serial number, and the hyphens separate a business unit code from a department name followed by something like 'LT' to denote a laptop.
I guess I need to echo the hostname and use a combination of sed, awk and perhaps cut to strip characters out to leave me with:
"BA PreSchool"
Any help much appreciated. This is what I have so far:
echo $HOSTNAME | sed 's/...\(...\)//' | sed 's/.local//'
echo "12345-BA-PreSchool-LT.local" | cut -d'-' -f2,3 | sed -e 's/-/ /g'
(Not on OSX, so not sure if cut is defined)
I like to keep things simple :)
You could do it with just cut:
echo 12345-BA-PreSchool-LT.local | cut -d"-" -f2,3
BA-PreSchool
If you want to remove the hyphen you can use tr
echo 12345-BA-PreSchool-LT.local | cut -d"-" -f2,3 | tr "-" " "
BA PreSchool
How about
echo $HOSTNAME | awk 'BEGIN { FS = "-" } ; { print $2, $3 }'
Awk can solve your question easily.
echo "12345-BA-PreSchool-LT.local" | awk -F'-' '$0=$2" "$3'
BA PreSchool
bash$ string="12345-BA-PreSchool-LT.local"
bash$ IFS="-"
bash$ set -- $string
bash$ echo $2-$3
BA-PreSchool

Resources