删除 Unix 上的部分路径

问题描述 投票:0回答:8

我正在尝试删除字符串中的部分路径。我有路径:

/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
是字符串的第二部分,我显然做错了什么......也许有更简单的方法?

shell unix scripting sed
8个回答
134
投票

如果您想删除特定 NUMBER 的路径组件,您应该将

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-
# output:
# some/deepish/dir

保留前两个组件:

echo $path | cut -d'/' -f-3
# output:
# /home/dude

删除最后两个组件(

rev
反转字符串):

echo $path | rev | cut -d'/' -f4- | rev
# output:
# /home/dude/some

保留最后三个组件:

echo $path | rev | cut -d'/' -f-3 | rev
# output:
# some/deepish/dir

或者,如果您想删除特定组件之前的所有内容,

sed
可以工作:

echo $path | sed 's/.*\(some\)/\1/g'
# output:
# some/deepish/dir

或在特定组件之后:

echo $path | sed 's/\(dude\).*/\1/g'
# output:
# /home/dude

如果您不想保留指定的组件,那就更容易了:

echo $path | sed 's/some.*//g'
# output:
# /home/dude/

如果你想保持一致,你也可以匹配尾部斜杠:

echo $path | sed 's/\/some.*//g'
# output:
# /home/dude

当然,如果您要匹配多个斜杠,则应该切换

sed
分隔符:

echo $path | sed 's!/some.*!!g'
# output:
# /home/dude

请注意,这些示例都使用绝对路径,您必须尝试使它们能够使用相对路径。


92
投票

您还可以使用 POSIX shell 变量扩展来执行此操作。

path=/path/to/file/drive/file/path/
echo ${path#/path/to/file/drive/}

当变量展开时,

#..
部分会去掉前导的匹配字符串;如果您的字符串已经在 shell 变量中(例如您正在使用
for
循环),这尤其有用。您还可以使用
%...
从变量末尾删除匹配的字符串(例如扩展名)。请参阅
bash
手册页了解血淋淋的细节。


33
投票

如果您不想对要删除的部分进行硬编码:

$ s='/path/to/file/drive/file/path/'
$ echo ${s#$(dirname "$(dirname "$s")")/}
file/path/

12
投票

使用 sed 执行此操作的一种方法是

echo /path/to/file/drive/file/path/ | sed 's:^/path/to/file/drive/::'

7
投票

如果你想删除路径的最后N个组件,你当然可以使用N调用

dirname
,如glenn的答案所示,但使用globbing可能更容易:

path=/path/to/file/drive/file/path/
echo "${path#*/*/*/*/*/}"   #  file/path/

具体来说,

${path#*/*/*/*/*/}
的意思是“返回
$path
减去包含5个斜杠的最短前缀”


3
投票

按照邪恶 otto 的建议使用

${path#/path/to/file/drive/}
无疑是执行此操作的典型/最佳方法,但由于有许多 sed 建议,值得指出的是,如果您使用固定字符串,则 sed 是多余的。你还可以这样做:

echo $PATH | cut -b 21-

丢弃前 20 个字符。同样,您可以在 bash 中使用

${PATH:20}
或在 zsh 中使用
$PATH[20,-1]


1
投票

纯粹的 bash,无需硬编码答案

basenames()
{
  local d="${2}"
  for ((x=0; x<"${1}"; x++)); do
    d="${d%/*}"
  done
  echo "${2#"${d}"/}"
}
  • 参数 1 - 您想保留多少级别(原问题中的 2 级)
  • 参数 2 - 完整路径

取自vsi_common原始版本


1
投票

这里有一个使用简单 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 上面提到的,在这种情况下,

#
符号用于删除前缀。

© www.soinside.com 2019 - 2024. All rights reserved.