如何从文本文件中删除某些行的固定部分?

如何从文本文件中删除某些行的固定部分?

我一直在使用ls -Rlh /path/to/directory > file一些文本文件记录某些硬盘驱动器中的内容。

我想在创建文本文件后删除一些字符串。

文本文件的一部分的示例是:

external1:
total 36K
drwxrwxr-x 2 emma emma 4.0K Oct 31 01:29 dir1
drwxrwxr-x 2 emma emma  12K Oct 31 01:29 dir2
drwxrwxr-x 2 emma emma  20K Oct 31 01:29 dir3

external1/dir1:
total 4.5M
-rw-rw-r-- 1 emma emma 769K Oct 31 01:12 a001.jpg
-rw-rw-r-- 1 emma emma 698K Oct 31 01:12 a002.jpg
-rw-rw-r-- 1 emma emma 755K Oct 31 01:12 a003.jpg
-rw-rw-r-- 1 emma emma 656K Oct 31 01:12 a004.jpg
-rw-rw-r-- 1 emma emma 756K Oct 31 01:12 a005.jpg
-rw-rw-r-- 1 emma emma 498K Oct 31 01:12 a006.jpg
-rw-rw-r-- 1 emma emma 455K Oct 31 01:12 a007.jpg

external1/dir2:
total 8.7M
-rw-rw-r-- 1 emma emma  952K Oct 31 01:13 a001.jpg
-rw-rw-r-- 1 emma emma  891K Oct 31 01:13 a002.jpg
-rw-rw-r-- 1 emma emma  838K Oct 31 01:13 a003.jpg
-rw-rw-r-- 1 emma emma  846K Oct 31 01:13 a004.jpg
-rw-rw-r-- 1 emma emma  876K Oct 31 01:13 a005.jpg
-rw-rw-r-- 1 emma emma  834K Oct 31 01:13 a006.jpg
-rw-rw-r-- 1 emma emma  946K Oct 31 01:13 a007.jpg
-rw-rw-r-- 1 emma emma  709K Oct 31 01:13 a008.jpg
-rw-rw-r-- 1 emma emma 1007K Oct 31 01:13 a009.jpg
-rw-rw-r-- 1 emma emma  940K Oct 31 01:13 a010.jpg

external1/dir3:
total 4.6M
-rw-rw-r-- 1 emma emma 408K Oct 31 01:15 a001.jpg
-rw-rw-r-- 1 emma emma 525K Oct 31 01:15 a002.jpg
-rw-rw-r-- 1 emma emma 383K Oct 31 01:15 a003.jpg
-rw-rw-r-- 1 emma emma 512K Oct 31 01:15 a004.jpg
-rw-rw-r-- 1 emma emma 531K Oct 31 01:15 a005.jpg
-rw-rw-r-- 1 emma emma 532K Oct 31 01:15 a006.jpg
-rw-rw-r-- 1 emma emma 400K Oct 31 01:15 a007.jpg
-rw-rw-r-- 1 emma emma 470K Oct 31 01:15 a008.jpg
-rw-rw-r-- 1 emma emma 407K Oct 31 01:15 a009.jpg
-rw-rw-r-- 1 emma emma 470K Oct 31 01:15 a010.jpg

实际的文本文件有数千行长,大小为几兆字节。

我想要做的是从每个适用行中删除文件大小之前的所有内容,以便每行都以文件大小开头。例如

512K Oct 31 01:15 a004.jpg
531K Oct 31 01:15 a005.jpg
532K Oct 31 01:15 a006.jpg
400K Oct 31 01:15 a007.jpg
470K Oct 31 01:15 a008.jpg

但是,我想保持所有其他行(包含目录名称和总大小)完整,所以这意味着我不能使用colrmor cut

答案1

解析 的输出ls是不可靠的,但这在这种特殊情况下应该有效:

sed -e 's/^.*emma emma //' file

这将删除每行上直到“emma emma”的所有内容。如果该字符串没有出现在一行中,则它没有改变。

我编写的正则表达式仅删除 emma 之后的第一个空格,以便大小字段保持右对齐(例如“709K”和“1007K”都在行上采用相同数量的字符)

如果你不想这样做,请使用这个:

sed -e 's/^.*emma emma  *//' file

这将删除 emma 之后的所有空格,直到下一个字段的开始。

这是一个适用于 any 的 sed 版本user group

sed -e 's/^.\{10\} [0-9]\+ [^ ]\+ [^ ]\+ //' file

它更加依赖于ls输出的确切格式,因此它在技术上比第一个版本更糟糕......但它应该适用于您的特定文件。

为什么*不*解析`ls`?有关为什么解析 ls 不好的信息。


如果并非所有文件都属于emma,您可能需要使用像这样的 awk 脚本。

awk 'NF>2 {print $5,$6,$7,$8,$9} ; NF<3 {print}' file

对于包含 2 个以上字段的行,它仅打印字段 5-9。对于包含 <3 个字段的行,它会打印整行。不幸的是,这会丢失大小字段的右对齐......可以使用稍微复杂的awk脚本来修复:

awk 'NF>2 {printf "%5s %s %s %s %s\n", $5, $6, $7, $8, $9} ; NF<3 {print}' file 

这个最终版本合并了 jasonwryan 答案中的 for 循环,因此可以处理其中包含任意数量的单个空格的文件名(但不是连续的空格,如 G-Man 提到的):

awk 'NF>2 {printf "%5s", $5; for(i=6;i<=NF;i++){printf " %s", $i}; printf "\n"} ; NF<3 {print}' file 

答案2

使用awk:

awk '{if ($1 ~/^-|d/) {for(i=5;i<=NF;i++){printf "%s ", $i}; printf "\n"} else print $0}' file

如果第一个字段以-或开头d;然后从第五个字段到最后一个字段打印,否则打印整个记录。

答案3

由于您谈论的是 100 MB 的数据,因此可能值得使用gnu ls 的-o-g选项来避免打印用户和组,从而产生以下格式:

-rw-rw-r-- 1 952K Oct 31 01:13 a001.jpg

此 sed 命令将删除行开头不需要的数据:

sed 's/^[-a-z]{10} \{1,\}[0-9]\{1,\}//'

您可以将列出和删除不需要的数据合并为一个步骤(这也适用于本页上的大多数解决方案),这也可以节省您一些时间:

ls -Rlhog /path/to/directory | sed 's/^[-a-z]\{10\} \{1,\}[0-9]\{1,\}//' > file

相关内容