正则表达式:如何匹配到一个字符或一行的结束?



我试图按照如下方式分离出路径的部分。我的输入路径采用以下可能的形式:

bucket
bucket/dir1
bucket/dir1/dir2
bucket/dir1/dir2/dir3
...

我想将路径的第一部分(bucket)与字符串的其余部分(dir1/dir2/dir3/...)分开,并将两者存储在单独的变量中。

下面给了我一些接近我想要的东西:

❯ BUCKET=$(echo "bucket/dir1/dir2" | sed 's@(^[^/]*)[/](.*)@1@')
❯ EXTENS=$(echo "bucket/dir1/dir2" | sed 's@(^[^/]*)[/](.*)@2@')
echo $BUCKET $EXTENS
❯ bucket dir1/dir2

然而,如果我只有bucket作为输入(没有斜杠),它会失败:

❯ BUCKET=$(echo "bucket" | sed 's@(^[^/]*)[/](.*)@1@')
❯ EXTENS=$(echo "bucket" | sed 's@(^[^/]*)[/](.*)@2@')
echo $BUCKET $EXTENS
❯ bucket bucket

…因为,在没有第一个'/'的情况下,不会发生捕获,因此不会发生替换。当输入仅为'bucket'时,我希望将$EXTENS设置为空字符串""

谢谢!

对于如此简单的事情,您可以使用内置bash而不是启动sed:

$ path="bucket/dir1/dir2"
$ bucket="${path%%/*}"
$ extens="${path#$bucket}"
$ printf '|%s|%s|n' "$bucket" "$extens"
|bucket|/dir1/dir2|
$ path="bucket"
$ bucket="${path%%/*}"
$ extens="${path#$bucket}"
$ printf '|%s|%s|n' "$bucket" "$extens"
|bucket||

但是如果你真的想使用sed和捕获组:

$ declare -a bucket_extens
$ mapfile -td '' bucket_extens < <(printf '%s' "bucket/dir1/dir2" | sed -E 's!([^/]*)(.*)!1x002!')
$ printf '|%s|%s|n' "${bucket_extens[@]}"
|bucket|/dir1/dir2|
$ mapfile -td '' bucket_extens < <(printf '%s' "bucket" | sed -E 's!([^/]*)(.*)!1x002!')
$ printf '|%s|%s|n' "${bucket_extens[@]}"
|bucket||

我们使用扩展正则表达式(-E)来简化位,并使用!作为替换命令的分隔符。第一个捕获组是不包含斜杠的任何内容,第二个捕获组是其他所有内容,如果没有其他内容,则不包含任何内容。

在替换字符串中,我们用NUL字符(x00)分隔两个捕获组。然后使用mapfile将结果赋值给bash数组bucket_extens

NUL技巧是一种处理文件名中包含空格,换行符…NUL是唯一不能成为文件名一部分的字符。mapfile-d ''选项表示要映射的行以NUL分隔,而不是默认的换行符。

不要捕捉任何内容。相反,只需匹配您不想要的并将其替换为空:

BUCKET=$(echo "bucket" | sed 's@/.*@@').          # bucket
BUCKET=$(echo "bucket/dir1/dir2" | sed 's@/.*@@') # bucket
EXTENS=$(echo "bucket" | sed 's@[^/]*@@')           # blank
EXTENS=$(echo "bucket/dir1/dir2" | sed 's@[^/]*@@') # /dir1/dir2

当你在正则表达式中放入斜杠时。没有斜杠的字符串不会匹配。让我们将斜杠设置为可选的/?。(?前的反斜杠由于sedBRE,这是必需的。)那你可以试试:

#!/bin/bash
#path="bucket/dir1/dir2"
path="bucket"
bucket=$(echo "$path" | sed 's@(^[^/]*)/?(.*)@1@')
extens=$(echo "$path" | sed 's@(^[^/]*)/?(.*)@2@')
echo "$bucket" "$extens"
  • 你不需要在斜杠前加上反斜杠
  • 按照惯例,建议用户变量使用小写。

最新更新