2012-06-11 121 views
31

我试图删除部分路径中的字符串。我有路径:Unix删除部分路径

/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是字符串的第二部分,我清楚地做错了什么......也许还有一个更简单办法?与sed的做到这一点

回答

28

您还可以使用POSIX shell变量扩展做到这一点。

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

当变量被展开时,#..部分去掉了前导匹配的字符串;如果你的字符串已经在shell变量中,比如你使用for循环,这个特别有用。您也可以使用%...从变量末尾剥离匹配的字符串(例如,扩展名)。请参阅bash手册页以了解血腥详细信息。

+0

谢谢...是的,我正在使用shell变量来执行此操作。这两部分都是变量,我需要删除的部分和完整路径。 – esausilva

+0

优秀!但是,当字符串“从管道”进入时,我怎么能使用它? – gromit190

+0

@Birger如果字符串来自管道,那么你需要把它变成一个变量来使用shell变量扩展。或者在这种情况下只使用'sed'。 –

9

一种方法是

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

谢谢。这很好用 – esausilva

+0

真棒 - 我不知道sed分隔符可能是“:”(冒号)而不是“/”(斜杠)。优雅和完美的作品。 – stachyra

+0

您可以使用几乎任何分隔符与sed,不只是/和:只要你是一致的。 –

18

如果你不想硬编码您要移除的部分:

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

我花了2个小时看如何做到这一点。你是唯一一个发布方式来显示没有硬编码的目录名称的唯一方法。我需要做的是:'find/path/to/file/drive/file/* _ TST -maxdepth 0 -type d'但是我只想显示目录的完整路径名称。这做到了。 – Whitecat

+0

@Whitecat就是你想要的,阅读“man find”,特别是“-printf”。你可以指定'-printf'%h \ n“'。请记住,它将打印每个匹配文件的目录,因此您希望通过“uniq”进行过滤。 –

3

使用${path#/path/to/file/drive/}邪恶奥托的建议肯定是要做到这一点,典型的/最好的方法,但因为有许多SED建议值得指出的是,如果您使用固定字符串工作,sed是过度的。您也可以这样做:

echo $PATH | cut -b 21- 

放弃前20个字符。同样,您可以在bash中使用${PATH:20}或在zsh中使用$PATH[20,-1]

+0

谢谢。我正在使用邪恶的奥托的答案。我想要移除的部分是固定的,但如果将脚本移动到不同的框/不同路径,可以更改。所以,我想从变量的路径中删除部分使得它比计数更容易....但您提供的信息是很好知道:) – esausilva

2

如果你想删除路径的第N个部分,你当然可以使用ň调用basename,如glenn's answer,但它可能是更容易使用通配符:

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

具体而言,${path#*/*/*/*/*/}表示“返回$path减去包含5个斜杠的最短前缀”

32

如果要删除某个数量的路径组件,应该使用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 

请注意,这些示例都使用绝对路径,您必须四处游览才能使它们适用于相对路径。

+0

令人惊叹的答案,特别是双'rev'技巧。当我的投票帽明天褪去时,我会投票赞成。 –

+1

在原始的Unix精神中出色的信息答案,并且比{chopsquiggleSquiggle}更好:只有:shellversionyoumaynothave。 –