我正在尝试删除字符串中的部分路径。我有路径:
/path/to/file/drive/file/path/
我想删除第一部分/path/to/file/drive
并生成输出:
file/path/
注意:我在while循环中有几个路径,在所有路径中都有相同的/path/to/file/drive
,但我只是在寻找删除所需字符串的“方法”。
我找到了一些例子,但我无法让它们起作用:
echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:\2:'
echo /path/to/file/drive/file/path/ | sed 's:/path/to/file/drive:2'
\2
是字符串的第二部分,我显然做错了...也许有一种更简单的方法?
答案 0 :(得分:62)
如果您要删除特定数量的路径组件,则应将cut
与-d'/'
一起使用。例如,如果path=/home/dude/some/deepish/dir
:
删除前两个组件:
# (Add 2 to the number of components to remove to get the value to pass to -f)
$ echo $path | cut -d'/' -f4-
some/deepish/dir
保留前两个组件:
$ echo $path | cut -d'/' -f-3
/home/dude
删除最后两个组件(rev
反转字符串):
$ echo $path | rev | cut -d'/' -f4- | rev
/home/dude/some
保留最后三个组成部分:
$ echo $path | rev | cut -d'/' -f-3 | rev
some/deepish/dir
或者,如果您要删除特定组件之前的所有内容,sed
将起作用:
$ echo $path | sed 's/.*\(some\)/\1/g'
some/deepish/dir
或在特定组件之后:
$ echo $path | sed 's/\(dude\).*/\1/g'
/home/dude
如果您不想保留您指定的组件,那就更容易了:
$ echo $path | sed 's/some.*//g'
/home/dude/
如果你想保持一致,你也可以匹配尾随斜杠:
$ echo $path | sed 's/\/some.*//g'
/home/dude
当然,如果您要匹配多个斜杠,则应切换sed
分隔符:
$ echo $path | sed 's!/some.*!!g'
/home/dude
请注意,这些示例都使用绝对路径,您必须使用它们来使它们与相对路径一起使用。
答案 1 :(得分:43)
您也可以使用POSIX shell变量扩展来执行此操作。
path=/path/to/file/drive/file/path/
echo ${path#/path/to/file/drive/}
#..
部分在扩展变量时剥离前导匹配字符串;如果您的字符串已经在shell变量中,那么这非常有用,例如,如果您使用for
循环。您也可以使用%...
从变量的末尾剥离匹配的字符串(例如,扩展名)。有关详细信息,请参阅bash
手册页。
答案 2 :(得分:24)
如果您不想对要删除的部分进行硬编码:
$ s='/path/to/file/drive/file/path/'
$ echo ${s#$(dirname "$(dirname "$s")")/}
file/path/
答案 3 :(得分:9)
使用sed执行此操作的一种方法是
echo /path/to/file/drive/file/path/ | sed 's:^/path/to/file/drive/::'
答案 4 :(得分:4)
使用邪恶otto建议的${path#/path/to/file/drive/}
肯定是典型/最好的方法,但由于有很多sed建议,值得指出的是,如果你使用的是固定字符串,sed就是矫枉过正。你也可以这样做:
echo $PATH | cut -b 21-
丢弃前20个字符。同样,您可以在bash中使用${PATH:20}
或在zsh中使用$PATH[20,-1]
。
答案 5 :(得分:4)
如果您要删除路径的前N个部分,您当然可以使用 N 调用dirname
,如glenn's answer但是,使用globbing可能更容易:
path=/path/to/file/drive/file/path/
echo "${path#*/*/*/*/*/}" # file/path/
具体来说,${path#*/*/*/*/*/}
表示"返回$path
减去包含5个斜杠的最短前缀" 。
答案 6 :(得分:0)
纯粹的bash,没有硬编码答案
basenames()
{
local d="${2}"
for ((x=0; x<"${1}"; x++)); do
d="${d%/*}"
done
echo "${2#"${d}"/}"
}
答案 7 :(得分:0)
这是一个使用简单 bash 语法的解决方案,它可以容纳变量(以防您不想对完整路径进行硬编码),不需要将标准输入管道传输到 sed
,并包含一个 for
循环, 很好的衡量标准:
FULLPATH="/path/to/file/drive/file/path/"
SUBPATH="/path/to/file/drive/"
for i in $FULLPATH;
do
echo ${i#$SUBPATH}
done
正如@evil otto 上面提到的,#
符号用于在这种情况下删除前缀。