Regex 如何使正则表达式与文件路径匹配?

Regex 如何使正则表达式与文件路径匹配?,regex,bash,grep,Regex,Bash,Grep,我已经用这个命令玩了一两个小时了,恐怕我已经失去了客观性目标是只匹配提供给bash的相对文件路径。 第一个相对路径或/some/file/path 第二个相对路径是。或。/some/file/path 其中“/some/file/path”的长度是任意的 我一直在使用bash中的grep试图找出如何在我的脚本中实现它,这样我就可以将它扩展到它的绝对文件路径,从而/some/file/path或。/some/file/path变成/the/absolute/file/path;我已经弄明白了 我的

我已经用这个命令玩了一两个小时了,恐怕我已经失去了客观性目标是只匹配提供给bash的相对文件路径。

第一个相对路径
/some/file/path

第二个相对路径是
。/some/file/path

其中“/some/file/path”的长度是任意的

我一直在使用
bash
中的
grep
试图找出如何在我的脚本中实现它,这样我就可以将它扩展到它的绝对文件路径,从而
/some/file/path
。/some/file/path
变成
/the/absolute/file/path
;我已经弄明白了

我的问题是匹配相对路径。

我一直使用的代码是

echo "../some/file/path" | egrep '\.{1}/?[[:graph:]]?+$'

我把我的问题缩小到

echo ".." | egrep '\.{2}'
只要点出现了
2+n
次,就会与点匹配,不完全是预期的2次出现。当我将其更改为

echo ".." | egrep '\.{1}' 
由于某种原因,我想不出是否会匹配

最终的实现应该是这样工作的

 41 _expand_relative_path () {
 42         if [[ "$1" =~ ^\.{1}/?[[:graph:]]?+$ ]]; then
 43                 echo "."
 44         elif [[ "$1" =~ ^\.{2}/?[[:graph:]]?+$ ]]; then
 45                 echo ".."
 46         else    
 47                 echo "$1"
 48         fi
 49 }

根据我的课本,如果说明符{n}恰好出现n次,它将与前面的元素匹配。但它不会那样做!如果是n次或更多次,则匹配!我做错了什么?

匹配相对路径的正则表达式不是以斜杠开头的:

^[^/].*

^\.{1}/?[[:graph:][]?+$
的问题是,
/
已被指定为可选,以下
[[:graph:][]
字符类与任何可见字符匹配,包括更多句点。另外,你已经用
?+
量化了你的角色类,意思是“零或一次,占有”:它不必匹配,但如果匹配,它不会“放弃”匹配的内容,让其他模式尝试成功-可能不是你想要的

当你说
echo..“|egrep'\.{2}'
时,你所说的是“字符串在某个点上包含一行两个句点”-但这并不意味着它不能有更多的句点或其他任何东西,不管怎样,没有
^
$
锚定,这将限制为精确且只有两个句点

正如其他人所注意到的,任何不以
/
开头的路径都是相对的,因此
^[^/].
可以工作。但是,如果要查找文本文件中包含其他文本的相对路径,这可能很有用:

(\.{1,2}(?:\/[[:alnum:]]*)*)
输出:

将匹配点,只要它有2+n个引用,而不是正好2个 如预期的那样

嗯,是的。默认情况下,
grep
打印包含图案的行。任何包含两个以上连续点的线都必须包含两个连续点,因此图案匹配

当我将其更改为

echo ".." | egrep '\.{1}' 
由于某种原因,我想不出是否会匹配

同样的事情:字符串“.”包含一个“.”,因此它与模式匹配

现在,考虑一下您的原始模式,
'\.{2}/?[[:graph:]?+$'

  • 首先,注意它没有锚定到字符串的开头,因此它将匹配表单
    /foo/bar../baz
    (和其他)的绝对路径。在模式中需要一个初始的
    ^
    来锚定它
  • 通过使用
    量词,可以选择在前导点后出现
    /
    。如果您的目标是专门匹配第一段为
    的路径,则不清楚为什么要这样做。
    。我能想到的唯一一件事是,您希望匹配路径,该路径恰好是
    本身,您的模式确实如此,但它太容易接受
  • 下一段是
    [[:graph:][]?+
    ,这似乎是编写更标准的
    [[:graph:][]*
    的一种奇怪的方式。此外,您似乎依赖于这样一个事实,即
    [[:graph:]
    将匹配它将匹配的
    /
    字符,因此您最好将前面的可选
    /
    直接滚动到character类中:
    '^\.{2}[:graph:]*$'
  • 现在观察
    [[:graph:]
    也匹配
    。现在,这解释了为什么原始模式匹配包含两个以上连续点的字符串:前两个由
    \.{2}
    匹配,没有任何内容由
    /?
    匹配,其余的点(可能还有其他字符)由
    [[:graph:][]匹配
  • 最后,考虑<<代码> \>代码>比<代码> > { 2 }更短更清晰,特别是那个平原<代码> \ <代码>远比<代码> > { 1 } 当然,在他的回答中,@Bohemian提供了匹配每个可能的相对路径的自然模式,但是如果您想要一个模式专门匹配第一个段是
    的路径,包括那些没有其他段,并且没有尾随的
    //code>的路径,那么您可以尝试以下方法:

    egrep '^\.{1,2}(/.*[^/])?$'
    
    • 它被锚定在开头(
      ^
      )和结尾(
      $
      ),因此它只执行整行匹配
    • 匹配行必须以一个或两个点开始(
      \.{1,2}
    • 其他任何内容都是可选的(
      (…)?
      ),但如果存在该可选段,则它必须以
      /
      开头,并以非
      /
      的字符结尾。中间可以是任何字符的任何数字,包括零(
      *
    • 请注意,Unix文件名和目录名可以包含空格和非图形字符,因此在原始模式中使用
      [:graph://code>将其限制为可能路径的子集
    适用于Windows:
    ^.\\\(?!.\\)(.*)$

    或者对于Linux:
    ^.*/(?!.*/)(.*)$

    或两者皆适用:

    ^.*(:\\\\\\/)(?!.*(:\\\\\\\/)(*))
    
    echo ".." | egrep '\.{1}' 
    
    egrep '^\.{1,2}(/.*[^/])?$'