我一直在玩这个命令大约一两个小时,我担心我可能失去了客观性。 目标是仅匹配给予bash的相对文件路径。
第一条相对路径.
或./some/file/path
第二条相对路径为..
或../some/file/path
" / some / file / path"的长度是任意的。
我一直在grep
内使用bash
来尝试找出如何在我的脚本中实现它,以便我可以将其扩展到它的绝对文件路径所以./some/file/path
或../some/file/path
变为/the/absolute/file/path
;我已经弄清楚了。
我的问题是匹配相对路径。
我一直在使用的代码是
echo "../some/file/path" | egrep '\.{1}/?[[:graph:]]?+$'
和
echo "../some/file/path" | egrep '\.{2}/?[[: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次或更多次匹配!我做错了什么?
答案 0 :(得分:4)
匹配相对路径的正则表达式不是以斜杠开头的:
^[^/].*
答案 1 :(得分:1)
^\.{1}/?[[:graph:]]?+$
的问题是/
已被指定为可选,并且以下[[:graph:]]
字符类匹配任何可见,包括更多句点。此外,您已使用?+
量化了您的角色等级,这意味着&#34;零或一次,占有欲&#34;:它无法匹配,但如果确实如此,则不会& #34;放弃&#34;是什么让这个模式的其余部分试图成功 - 可能不是你想要的那样。
当你说echo ".." | egrep '\.{2}'
时,你所说的是&#34;字符串在某个时刻包含连续两个句点&#34; - 但这并不意味着它可以拥有更多的句号或其他任何内容,而不是没有^
和$
锚定,这将限制完全且仅> 两个时期。
正如其他人所说,任何不以/
开头的路径都是相对的,因此^[^/].*
有效。但是,如果您想要查找文本文件中包含其他文本的相对路径,这可能很有用:
(\.{1,2}(?:\/[[:alnum:]]*)*)
regex demo输出:
答案 2 :(得分:1)
只要有2 + n次出现,echo ".." | egrep '\.{2}'
就会匹配点,而不是2 按预期发生。
是的。默认情况下,grep
会打印包含模式的行。任何包含两个以上连续点的线必然包含两个连续点,因此模式匹配。
当我将其更改为
时,会发生同样的事情echo ".." | egrep '\.{1}'
仍然会因某些原因而无法匹配。
同样的事情:字符串&#34; ..&#34;包含&#39;。&#39;因此它匹配模式。
现在考虑一下您的原始模式,'\.{2}/?[[:graph:]]?+$'
:
/foo/bar../baz
(和其他)的绝对路径。您需要在模式中使用初始^
来锚定它。/
量词可以在前导点可选后显示?
。如果您的目标专门用于匹配第一个分段为..
的路径,则不清楚为什么要这样做。我唯一能想到的是你想要匹配你的模式所具有的..
本身的路径,但它太接受了。[[:graph:]]?+
,这似乎是编写更标准[[:graph:]]*
的奇怪方式。此外,您似乎依赖于[[:graph:]]
将匹配/
字符的事实,因此您可以将前面的可选/
权限滚动到字符类中:'^\.{2}[[:graph:]]*$'
。[[:graph:]]
匹配.
。这现在解释了为什么原始模式匹配包含两个以上连续点的字符串:前两个由\.{2}
匹配,没有任何内容与/?
匹配,剩余的点(可能还有其他字符)由[[:graph:]]?+
匹配。\.\.
比\.{2}
更短更清晰,尤其是\.
远比\.{1}
更清晰。< / LI>
醇>
当然,在他的回答中,@ Bohemian提供了匹配每个可能的相对路径的自然模式,但是如果你想要一个模式专门匹配第一个段为.
或..
的路径,包括那些没有其他段,没有尾随/
的那些你可以试试这个:
egrep '^\.{1,2}(/.*[^/])?$'
^
)和结尾($
),因此它执行整行匹配(仅限)。\.{1,2}
)(...)?
),但如果存在该可选段,则它必须以/
开头,并以不是/
的字符结尾。中间可以是任何字符(.*
)的任何数字,包括零。[:graph:]
会将其限制为可能路径的子集。答案 3 :(得分:0)
对于Windows:^.*\\(?!.*\\)(.*)$
或Linux:^.*/(?!.*/)(.*)$
或两者兼有:
^.*(?:\\|/)(?!.*(?:\\|/))(.*)$
它与filename.extension
或.../path/filename.extension
中的...\path\filename.extension
匹配,因为它会检查\
或/
的最后一次出现,然后从中检出每个字符那一点。