Here's my situation. Currently, I have a script that accepts two arguments: book name and chapter name. For example:
$ myscript book1 chap1
Now, for reasons that would take a long time to explain, I would prefer my script to be able to take a single argument of the following format: {book name}.{chapter name}. For example:
$ myscript book1.chap1
The difficulty for me is that I do not know how to take a string $1=abc.xyz and turn it into two separate variables, $var1=abc and $var2=xyz. How can I do this?
If it's just two tags you can use a bash expression
arg=$1
beforedot=${arg%.*}
afterdot=${arg#*.}
It's faster than cut
because it's a shell builtin. Note that this puts everything before the first last dot into beforedot
and everything after into afterdot
.
EDIT:
There's also a substitution/reinterpretation construct if you want to split by an arbitrary number of tokens:
string=a.b.c.d.e
tokens=(${string//\./ })
You're replacing dots by spaces and then that gets interpreted as an array declaration+definition because of the parentheses around it.
However I've found this to be less portable to bash' siblings and offspring. For example, it doesn't work in my favourite shell, zsh
.
Arrays need to be dereferenced with braces and are indexed from 0:
echo "Third token: ${tokens[2]}"
You can loop through them as well by dereferencing the whole array with [@]:
for i in ${tokens[@]}
do
# do stuff
done
For completeness and since you asked about a regex method:
pattern='^([^.]*)\.(.*)'
[[ $1 =~ $pattern ]]
book=${BASH_REMATCH[1]}
chapter=${BASH_REMATCH[2]}
The capture groups are elements in the BASH_REMATCH
array. Element 0 contains the whole match.
This regex will capture up to the first dot in the first element. Anything after the first dot including susbsequent dots will be in the second element. The regex can be easily modified to break on the last dot if needed.
If $arg
contains book.chap
read BOOK CHAP<<<$(IFS="."; echo $arg)
will set the variables BOOK and CHAP accordingly. This uses the bash internal field separator (IFS) which controls how bash understands word boundaries. If (say) you have multiple separators in your original $arg
then just specify further variables to contain the results.
From here:
$IFS defaults to whitespace (space, tab, and newline), but may be changed, for example, to parse a comma-separated data file
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With