我在文件中有一个类似这样的路径名列表:
/path/to/directory/one.txt
/longer/path/to/some/directory/two.py
/path/with spaces/in/it/three.sh
我想删除最后一次出现“/”之后的所有字符,因此上述所需的输出是:
/path/to/directory/
/longer/path/to/some/directory/
/path/with spaces/in/it/
答案1
sed 's![^/]*$!!'
这会执行以下操作:
- 使用除 之外的分隔符
/
,因为正则表达式包含/
. (我喜欢!
和 ,|
因为它们看起来像分割线;其他人使用@
、#
、^
或任何他们喜欢的东西。可以/
在由 分隔的正则表达式中使用/
,但这对于一个人来说可能很难阅读。) - 查找除 之外的(零个或多个)字符的字符串
/
。 (尽可能长。)但它必须位于行尾。 - 并用任何东西替换它。
注意:不包含任何字符的输入行将/
被完全擦除(即,该行的全部内容将被删除,只留下一个空白行)。如果我们想解决这个问题,并让没有斜线的行保持不变,我们可以将命令更改为
sed 's!/[^/]*$!/!'
这与第一个答案相同,只是它与最后一个答案匹配/
和它后面的所有字符,然后用 a 替换它们/
(实际上,将最后一个字符留/
在输入行中)。因此,当第一个答案找到one.txt
并将其替换为空时,这个答案会找到/one.txt
并将其替换为/
。但是,在不包含字符的行上/
,第一个答案匹配整行并将其替换为空,而这个答案找不到匹配项,因此不会进行替换。
我们可以/
在这个命令中使用分隔符,但是它必须是
sed 's/\/[^/]*$/\//'
通过在正则表达式和替换字符串前面添加“转义”斜杠后退斜杠 ( \
)。有些人发现这种“倾斜的树木”丛林更难以阅读和维护,但这基本上可以归结为风格问题。
答案2
您可以使用该dirname
实用程序:
xargs -I {} dirname {} <file.txt
这将为您提供列表中每个父目录的路径名。对于给定的列表,它将产生
/path/to/directory
/longer/path/to/some/directory
/path/with spaces/in/it
要在路径中嵌入换行符,请使用
/some/path with a \
newline/in/it
要嵌入引号,请将它们转义为例如\"
。