简体   繁体   中英

How to print character just after a particular character in a string using bash

I have a string like

abc def 0/1 dls dl 9/0 1//o

I want to take 0 and 1 (the characters just after and before the first / in the string) into two variables, say $NUM1 and $NUM2 , and do some further logic on them.

Using just shell parameter expansion :

$ str='abc def 0/1 dls dl 9/0 1//o'
$ num1=${str%%/*}    # Remove first "/" and everything after it
$ echo "$num1"
abc def 0
$ num1=${num1##* }   # Remove last space and everything before it
$ echo "$num1"
0
$ num2=${str#*/}     # Remove first "/" and everything before it
$ echo "$num2"
1 dls dl 9/0 1//o
$ num2=${num2%% *}   # Remove first space and everything after it
$ echo "$num2"
1

# , ## , % and %% have to be used carefully here. A single repetition removes the shortest match of the pattern following, and the double usage removes the longest pattern match.


Alternatively, after the first expansion, you just want the first or last character of the string, which can be solved with substring expansion:

$ echo "$num1"
abc def 0
$ echo "${num1:(-1)}"  # Extract last character
0
$ echo "$num2"
1 dls dl 9/0 1//o
$ echo "${num2:0:1}"   # Extract first character
1

Negative indices requires at least Bash 4.2. For older Bash versions, we can use

echo "${num1:${#num1}-1}"

And finally, we could use Bash regular expressions, as demonstrated in glenn jackman's answer .

You can use bash regular expressions, which populate the BASH_REMATCH array with the captured subexpressions:

if [[ $a =~ (.)/(.) ]]; then
  num1=${BASH_REMATCH[1]}
  num2=${BASH_REMATCH[2]}
fi
echo $num1 $num2
0 1

Don't get into the habit of using ALL_CAPS_VARNAMES: one day you'll accidentally write PATH=/my/path and then wonder why your script is broken. Leave upper case variables for the shell & OS

You can use sed to parse the line with regex to extract the numbers:

NUM1=$(echo 'abc def 0/1 dls dl 9/0 1//o' | sed 's@[^0-9]*\([0-9]*\)/[0-9]*.*@\1@')
NUM2=$(echo 'abc def 0/1 dls dl 9/0 1//o' | sed 's@[^0-9]*[0-9]*/\([0-9]*\).*@\1@')
echo $NUM1
0
echo $NUM2
1

I assume you are implicitly separating characters based on spaces. So you want the characters from the space to the first '/' and from the first '/' to the next space. I would probably use sed:

echo "abc def 0/1 dls dl 9/0 1//o" | sed -r 's%^[^/]* ([^ ]*)/([^ ]*) .*%\1 \2%'

But note this won't work if there are no spaces preceding the first '/'. You may wish to have another pattern for that case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM