一直在寻找有关正则表达式的一些更高级的正则表达式信息,并且没有找到关于它的更多信息。
这是概念,带有一个简单的字符串:
myString="DO-BATCH BATCH-DO"
if [[ $myString =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then
echo ${BASH_REMATCH[1]} #first perens
echo ${BASH_REMATCH[2]} #second perens
echo ${BASH_REMATCH[0]} #full match
fi
outputs:
BATCH
DO
DO-BATCH
第一场比赛(BATCH-DO)很好但我如何拉第二场比赛(DO-BATCH)?我只是在这里画一个空白,找不到关于bash正则表达式的很多信息。
答案 0 :(得分:3)
好的,所以我这样做的一种方法就是把它放在for循环中:
myString="DO-BATCH BATCH-DO"
for aString in ${myString[@]}; do
if [[ ${aString} =~ ([[:alpha:]]*)-([[:alpha:]]*) ]]; then
echo ${BASH_REMATCH[1]} #first perens
echo ${BASH_REMATCH[2]} #second perens
echo ${BASH_REMATCH[0]} #full match
fi
done
which outputs:
DO
BATCH
DO-BATCH
BATCH
DO
BATCH-DO
哪种方法有效,但我希望尽可能从一个正则表达式中提取所有内容。
答案 1 :(得分:1)
在您的回答中,myString
不是数组,但您使用数组引用来访问它。这适用于Bash,因为数组的第0个元素只能通过变量名来引用,反之亦然。这意味着您可以使用:
for aString in $myString; do
在这种情况下获得相同的结果。
在你的问题中,你说输出包括“BATCH-DO”。我得到“DO-BATCH”所以我认为这是一个错字。
在不使用for
循环的情况下获取额外字符串的唯一方法是使用更长的正则表达式。顺便说一句,我建议将Bash正则表达式置于变量中。它使某些类型更容易使用(例如,包含空格或特殊字符的那些类型。
pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))'
[[ $myString =~ $pattern ]]
declare -p BASH_REMATCH #dump the array
输出:
declare -ar BASH_REMATCH='([0]="DO-BATCH BATCH-DO" [1]="DO-BATCH" [2]="DO" [3]="BATCH" [4]="BATCH-DO" [5]="BATCH" [6]="DO")'
如果要捕获单个子串以及带连字符的短语,则需要额外的括号集。如果您不需要单个单词,则可以消除内部括号。
请注意,如果只需要提取子字符串,则无需使用if
。您只需要if
根据匹配进行条件操作。
另请注意,${BASH_REMATCH[0]}
与较长的正则表达式完全不同,因为它包含整个匹配。
答案 2 :(得分:1)
Per @Dennis Williamson的帖子我搞砸了,最后得到了以下内容:
myString="DO-BATCH BATCH-DO"
pattern='(([[:alpha:]]*)-([[:alpha:]]*)) +(([[:alpha:]]*)-([[:alpha:]]*))'
[[ $myString =~ $pattern ]] && { read -a myREMatch <<< ${BASH_REMATCH[@]}; }
echo "\${myString} -> ${myString}"
echo "\${#myREMatch[@]} -> ${#myREMatch[@]}"
for (( i = 0; i < ${#myREMatch[@]}; i++ )); do
echo "\${myREMatch[$i]} -> ${myREMatch[$i]}"
done
这很好用,除了myString必须有2个值。所以我发布这个,因为它有点有趣,我玩得很开心。但为了让它更通用并解决任何数量的配对组(即DO-BATCH),我将使用我原来答案的修改版本:
myString="DO-BATCH BATCH-DO"
myRE="([[:alpha:]]*)-([[:alpha:]]*)"
read -a myString <<< $myString
for aString in ${myString[@]}; do
echo "\${aString} -> ${aString}"
if [[ ${aString} =~ ${myRE} ]]; then
echo "\${BASH_REMATCH[@]} -> ${BASH_REMATCH[@]}"
echo "\${#BASH_REMATCH[@]} -> ${#BASH_REMATCH[@]}"
for (( i = 0; i < ${#BASH_REMATCH[@]}; i++ )); do
echo "\${BASH_REMATCH[$i]} -> ${BASH_REMATCH[$i]}"
done
fi
done
我会喜欢像多重比赛一样的perlre,但这很好。
答案 3 :(得分:0)
虽然这是一年前的问题(没有接受答案),但是正则表达式模式可以简化为:
myRE="([[:alpha:]]*-[[:alpha:]]*)"
删除内括号以找到更小(更简洁)的单词DO-BATCH
和BATCH-DO
?
18:10时间答案对你有用。 $ {BASH_REMATCH [0]}和$ {BASH_REMATCH [1]}导致找到2个单词。
答案 4 :(得分:0)
如果您实际上不知道提前会有多少匹配,您可以使用这个:
#!/bin/bash
function handle_value {
local one=$1
local two=$2
echo "i found ${one}-${two}"
}
function match_all {
local current=$1
local regex=$2
local handler=$3
while [[ ${current} =~ ${regex} ]]; do
"${handler}" "${BASH_REMATCH[@]:1}"
# trim off the portion already matched
current="${current#${BASH_REMATCH[0]}}"
done
}
match_all \
"DO-BATCH BATCH-DO" \
'([[:alpha:]]*)-([[:alpha:]]*)[[:space:]]*' \
'handle_value'