如何使用正则表达式提取 Bash 中的部分字符串
How to extract part of string in Bash using regex
我一直在尝试提取 bash 中的部分字符串。我在 Mac.
上使用它
输入字符串的模式:
- 一些随机单词后跟
/
。这是可选的。
- 关键字(
def
、foo
和 bar
)后跟连字符 (-
) 后跟数字。这可以是 2-6 位数字
- 这些数字后面又是连字符和几个连字符分隔的单词。
示例输入和输出:
abc/def-1234-random-words // def-1234
bla/foo-12-random-words // foo-12
bar-12345-random-words // bar-12345
所以我尝试按照命令来获取它,但由于某些奇怪的原因,它 returns 整个字符串。
extractedValue=`getInputString | sed -e 's/.*\(\(def\|bar\|foo\)-[^-]*\).*//g'`
// and
extractedValue=`getInputString | sed -e 's/.*\(\(def\|bar\|foo\)-\d{2,6}\).*//g'`
我还尝试使用 I
标志使其不区分大小写,但它为我抛出了错误:
: bad flag in substitute command: 'I'
以下是我试过的参考资料:
- Extract substring using regexp in plain bash
- Extract string from string using RegEx in the Terminal
这个 gnu sed
应该与忽略大小写标志一起使用:
sed -E 's~^(.*/){0,1}((def|foo|bar)-[0-9]{2,6})-.*~~I' file
def-1234
foo-12
bar-12345
这个 sed 匹配:
(.*/){0,1}
: 匹配一个字符串最多 /
可选地在开头
(
: 开始捕获组 #2
(def|foo|bar)
:匹配def
或foo
或bar
-
:匹配一个-
[0-9]{2,6}
:匹配2到6位数字
)
: 结束捕获组#2
-.*
:匹配 -
后跟任何内容直到结束
- 替换是我们在第 2 组中捕获的值
或者你可以使用这个 awk
:
awk -v IGNORECASE=1 -F / 'match($NF, /^(def|foo|bar)-[0-9]{2,6}-/) {print substr($NF, 1, RLENGTH-1)}' file
def-1234
foo-12
bar-12345
awk解释:
-v IGNORECASE=1
: 启用忽略大小写匹配
-F /
:使用/
作为字段分隔符
match($NF, /^(def|foo|bar)-[0-9]{2,6}-/)
:在 $NF
中使用正则表达式 ^(def|foo|bar)-[0-9]{2,6}-
匹配文本,这是使用 /
作为字段分隔符的最后一个字段(忽略 /
之前的文本)
- 如果匹配成功则使用
substr
打印从位置 1
到 RLENGTH-1
的文本(因为我们匹配到 -
之后的数字)
可以使用-E
选项来使用扩展正则表达式,那么就不用转义(
和|
.
echo abc/def-1234-random-words | sed -E -e 's/.*((def|bar|foo)-[^-]*).*//g'
def-1234
我一直在尝试提取 bash 中的部分字符串。我在 Mac.
上使用它输入字符串的模式:
- 一些随机单词后跟
/
。这是可选的。 - 关键字(
def
、foo
和bar
)后跟连字符 (-
) 后跟数字。这可以是 2-6 位数字 - 这些数字后面又是连字符和几个连字符分隔的单词。
示例输入和输出:
abc/def-1234-random-words // def-1234
bla/foo-12-random-words // foo-12
bar-12345-random-words // bar-12345
所以我尝试按照命令来获取它,但由于某些奇怪的原因,它 returns 整个字符串。
extractedValue=`getInputString | sed -e 's/.*\(\(def\|bar\|foo\)-[^-]*\).*//g'`
// and
extractedValue=`getInputString | sed -e 's/.*\(\(def\|bar\|foo\)-\d{2,6}\).*//g'`
我还尝试使用 I
标志使其不区分大小写,但它为我抛出了错误:
: bad flag in substitute command: 'I'
以下是我试过的参考资料:
- Extract substring using regexp in plain bash
- Extract string from string using RegEx in the Terminal
这个 gnu sed
应该与忽略大小写标志一起使用:
sed -E 's~^(.*/){0,1}((def|foo|bar)-[0-9]{2,6})-.*~~I' file
def-1234
foo-12
bar-12345
这个 sed 匹配:
(.*/){0,1}
: 匹配一个字符串最多/
可选地在开头(
: 开始捕获组 #2(def|foo|bar)
:匹配def
或foo
或bar
-
:匹配一个-
[0-9]{2,6}
:匹配2到6位数字
)
: 结束捕获组#2-.*
:匹配-
后跟任何内容直到结束- 替换是我们在第 2 组中捕获的值
或者你可以使用这个 awk
:
awk -v IGNORECASE=1 -F / 'match($NF, /^(def|foo|bar)-[0-9]{2,6}-/) {print substr($NF, 1, RLENGTH-1)}' file
def-1234
foo-12
bar-12345
awk解释:
-v IGNORECASE=1
: 启用忽略大小写匹配-F /
:使用/
作为字段分隔符match($NF, /^(def|foo|bar)-[0-9]{2,6}-/)
:在$NF
中使用正则表达式^(def|foo|bar)-[0-9]{2,6}-
匹配文本,这是使用/
作为字段分隔符的最后一个字段(忽略/
之前的文本)- 如果匹配成功则使用
substr
打印从位置1
到RLENGTH-1
的文本(因为我们匹配到-
之后的数字)
可以使用-E
选项来使用扩展正则表达式,那么就不用转义(
和|
.
echo abc/def-1234-random-words | sed -E -e 's/.*((def|bar|foo)-[^-]*).*//g'
def-1234