使用 basename :) 以下方法在您的输入中对我有用,但可能会遇到带引号的字符串等问题(感谢 Charles 指出这一点)。
cat mn_s3_files.txt | awk '{print $2}' | xargs basename
在 Linux 上,您可以使用 -d 和 xargs 来逐字处理所有字符。如果您收到 extra operand 错误,请尝试以下操作:
cat foo | awk '{print $2}' | perl -ne '$_ =~ s[.*/(.*)][$1]; print "$_";'
perl 版本非常暴力,即剥离所有内容,直到最后一行/。在这种情况下,您也许可以删除 awk。
如果你想在一行中完成
perl -ne 's[.*/(.*)][$1]; print "$_"' mn_s3_files.txt
或者您可以使用自动拆分并将分隔符更改为/
perl -F'/' -ane 'print "$F[4]"' mn_s3_files.txt
读者须知。
这个答案的其余部分试图回答来自 cmets 中 Charles 的问题。请注意,他关于 xargs 和引号的观点是完全有效的,即它们可能会导致问题,但在这种情况下它们并没有给我带来任何问题。
教育学
对于使用命令行、纯 Bash 解决方案或使用多个可能的命令和管道的解决方案的人来说,什么更具教学意义?我认为这是一个主观问题,没有正确答案。我选择了一种解决方案,即与我在问题中可以看到的内容密切相关的一种解决方案,即 OP 理解管道和cat,所以让我们使用它并以此为基础。我选择不采用最佳解决方案,因为最佳可能意味着任何事情。我可以用 C/C++ 编写一个速度极快的版本,但这似乎有点矫枉过正,可能对 OP 没有帮助。
Charles 对这个答案的一些 cmets 让我质疑自己对 *nix 的理解,所以我需要进一步解决这些问题。
Charles 在他的回答中说了以下让我有些惊讶的内容,强调我的...
您可以只使用 bash 中内置的功能来完成这一切 - 像 awk 或 xargs 或 basename 这样的任何东西都是不必要的低效率。
我决定对此进行测试,因为我没有在我使用过的机器上体验过这种情况,主要是多核 Mac 和 Linux。我在这里假设效率意味着运行脚本需要多长时间,因为如果应用于编写命令行等多长时间,这完全取决于使用它的人并且完全主观。我对纯 bash 解决方案进行了基准测试,即
#!/bin/bash
while read -r item path; do
name=${path##*/}
printf '%s\n' "$name"
done <mn_s3_files.txt
所用时间> 17分钟
real 17m34.959s
user 15m46.912s
sys 1m44.981s
这实际上比我想象的要长得多,事实上,在我创建的文件上,我最终杀死了两次脚本,以为出了点问题,因为我没想到它会这么慢。我仍然不相信有什么不对劲。 CPU 一直固定在 > 99%。
Charles还提到了以下...
awk 直接从 mn_s3_files.txt 读取比从 /bin/cat 写入的 FIFO 读取要快得多。
我怀疑在单核机器上这可能是真的,但在多核机器上它不是much faster。请注意,cat 非常高效,并且实际上会将大部分时间花在 IO 上,因为在这种情况下。管道读取端的应用程序读取速度明显慢于cat 写入速度。我用一堆类似于 OP 的数据创建了一个大文件。
time cat mn_s3_files.txt | awk '{print $2}' > /dev/null
real 0m59.017s
user 0m57.676s
sys 0m1.833s
相比
time awk '{print $2}' < mn_s3_files.txt > /dev/null
real 0m59.926s
user 0m58.266s
sys 0m1.468s
在这种情况下,首先想到的可能是fastest,对很多人来说就是猫。运行以下命令时
time cat mn_s3_files.txt | awk '{print $2}' | perl -ne '$_ =~ s[.*/(.*)][$1]; print "$_";' > /dev/null
real 1m6.614s
user 2m2.644s
sys 0m4.221s
cat 在我的机器上从未达到超过1% CPU。值得注意的是,awk 和 Perl 在整个过程中的 CPU 使用率都接近 100%,即它的效率要低得多。
Charles 提到start time 是他在讨论 bash 脚本时所指的效率提升...
Re:效率——本机 while 读取循环的好处是启动时间,而不是长流的运行时性能。如果处理少量数据,您可能希望使用 bash-native 内置工具,以及处理大量数据的外部工具(例如 awk)(启动外部工具的时间被实际执行处理所花费的时间所淹没)。
这对我来说似乎也违反直觉,所以我在小文件上对 bash 和 awk 进行了基准测试。对于一个只有三行的文件,启动时间对时间没有明显影响,在我的机器上多次运行时,awk 实际上快 整毫秒...
time splitter.sh > /dev/null
real 0m0.013s
user 0m0.002s
sys 0m0.006s
是时候 awk...
time awk '{gsub(/.*\//, "", $2); print $2}' < mn_s3_files2.txt > /dev/null
real 0m0.013s
user 0m0.002s
sys 0m0.006s
我也在一个空文件上做了这件事,而且 awk 更快。注意,此时我意识到查尔斯正在谈论在命令行中输入它,所以我尝试了,即
time while read -r item path; do name=${path##*/}; printf '%s\n' "$name"; done <mn_s3_files2.txt;
这是一个lot faster 而不是 awk (节省了高达 11 毫秒) 对于非常小的文件,即 完全扼杀性能 :)。
地球上最快的打字员
假设您是fastest typists on the planet 中的一员
世界上最快的打字员的最佳打字速度是每个字母大约 50 毫秒(请注意,我忽略了您可能需要在两个版本中使用大量奇怪字符的事实)。 bash 版本中的字符数约为 90,这意味着如果您以每个字符 50 毫秒的惊人速度输入,则需要大约 4 秒。 awk 版本大约有 50 个字符,因此这将花费您大约 2.5 秒的时间来输入。
因此,即使您是世界上最快的打字员,awk 版本也比 bash 版本快。
Charles 在另一条评论中说...
我不确定 cat mn_s3_files.txt | awk '{打印 $2}' | xargs basename 永远正确
永远正确部分不正确。我对 xargs 的原始答案和给定的输入字符串适用于以下版本的 mac 10.11.5,使用来自 OP 的输入没有问题。