如何使用bash在字符串中的特定字符之后打印字符

时间:2017-10-04 20:22:58

标签: regex bash shell scripting

我有一个像

这样的字符串
abc def 0/1 dls dl 9/0 1//o

我想将01(字符串中第一个/之前和之后的字符)转换为两个变量,比如$NUM1和{{1 },并对它们做一些进一步的逻辑。

4 个答案:

答案 0 :(得分:2)

仅使用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
此处必须谨慎使用

###%%%。单次重复将删除后续模式的最短匹配,并且双重用法将删除最长模式匹配。

或者,在第一次扩展之后,您只需要字符串的第一个或最后一个字符,可以通过子字符串扩展来解决:

$ 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

负指数至少需要Bash 4.2。对于较旧的Bash版本,我们可以使用

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

最后,我们可以使用Bash正则表达式,如glenn jackman's answer中所示。

答案 1 :(得分:2)

您可以使用bash正则表达式,使用捕获的子表达式填充BASH_REMATCH数组:

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

不要养成使用ALL_CAPS_VARNAMES的习惯:有一天你会不小心写PATH=/my/path,然后想知道为什么你的脚本坏了。为shell保留大写变量& OS

答案 2 :(得分:1)

您可以使用sed解析带有正则表达式的行来提取数字:

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

答案 3 :(得分:1)

我假设您是基于空格隐式分隔字符。所以你想要从空间的角色到第一个' /'从第一个' /'到下一个空间。我可能会使用sed:

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

但请注意,如果在第一个' /'之前没有空格,这将无法奏效。你可能希望有另一种模式。