0

我管理一个有 40 台 ubuntu 机器的计算机实验室,我拼凑了这个命令来查找学生主目录中大于 100M 的文件的总磁盘使用情况:

for i in `cat ./lab-machines.txt ` ; do ssh $i "nohup find /home -size +100M -print0 | du --files0-from=- -ch | tail -1 && hostname && ls /home" ; done > lab-disk-usage.txt

文件“lab-machines.txt”在单独的一行中包含计算机的主机名。该命令从一个配置了无密码登录的服务器运行到 root 用户的实验室机器。文件 lab-disk-usage.txt 中的输出包含每台机器的类似内容(我在括号中插入了注释):

69G total    
hostname
student-username (changes)
admin-username (always the same)
lost+found (always the same)

我希望每台机器的输出看起来像这样:

69G 主机名 学生-用户名

我对文本过滤不够熟悉,无法及时完成。你能帮我吗?

4

5 回答 5

1

tr通过命令管道输出

您可以尝试更简单的解决方案,例如通过tr命令管道输出。例如:

tr -s "\n" ' ' < lab-disk-usage.txt

不过,这假设文件中只有一条记录。如果您计划拥有多条记录,则需要先通过tr管道过滤每条记录,然后再将其附加到输出文件。例如:

your_pipeline_commands | tr -s "\n" ' ' > lab-disk-usage.txt

使用 Perl 的触发器运算符

如果您有一组多行记录,则需要更加聪明。Perl 在处理多行记录方面比 AWK 提供了一些优势,包括触发器运算符。例如:

perl -ne 'if ( /total/../^lost/ ) {
              chomp $_; print $_ . " "
          } else {
              print "\n"
          };
          END { print "\n" };' lab-disk-usage.txt

根据您的实际语料库,您可能需要稍微调整正则表达式以使事情正常工作,但在我的系统上它做正确的事情。

用于测试 Perl 的语料库

69G total
hostname
student-username
admin-username
lost+found

69G total
hostname
student-username
admin-username
lost+found

Perl 的示例输出

69G total     hostname student-username admin-username lost+found 
69G total     hostname student-username admin-username lost+found 
于 2013-03-02T17:38:17.283 回答
1

尝试这个:

awk -vORS=" " 'NR==1{sub("total","")}NR<=3' file
于 2013-03-02T17:15:32.730 回答
1

我稍微修改了您的示例数据:

69G total    
host1
jane
admin-username
lost+found
65G total    
host2
albert
admin-username
lost+found

这可以变成一个表格:

[ghoti@pc ~/tmp]$ awk 'NR%5==1{size=$1} NR%5==2{host=$1} NR%5==3{user=$1; printf("%-8s%-16s%s\n", size, host, user)}' lab-disk-usage.txt
69G     host1           jane
65G     host2           albert

她最重要的是我们使用模运算符 ( NR%5) 来确定我们在每组五行中的位置。

如果您不能依赖每组五行,那么请澄清您的输入数据的结构。还有其他方法可以检测记录边界,例如查找/[0-9]+G total$/,如果NR%5不能使用:

[ghoti@pc ~/tmp]$ awk '/G total$/{size=$1; getline host; getline user; printf("%-8s%-16s%s\n", size, host, user)}' lab-disk-usage.txt 
69G     host1           jane
65G     host2           albert

这基本上只是 potong 的GNU sed建议的 awk 版本,它也可以移植(即不仅仅是 GNU sed):

[ghoti@pc ~/tmp]$ sed -ne '/G total/{s/ .*//;N;N;s/\n/  /g;p;}' lab-disk-usage.txt 
69G  host1  jane
65G  host2  albert
于 2013-03-02T17:26:25.600 回答
0

如果记录之间没有空行,您可以先引入一个:

awk '/total/{print x}1' | awk '{print $1,$3,$4}' RS= OFS='\t' 

带有文件内容:

69G total    
host1
jane
admin-username
lost+found
65G total    
host2
albert
admin-username
lost+found

这会产生:

69G host1   jane
65G host2   albert

如果记录之间已经有一个空行,您可以跳过管道之前的部分并使用:

awk '{print $1,$3,$4}' RS= OFS='\t' file
于 2013-03-02T19:52:58.130 回答
0

这可能对您有用(GNU sed):

sed -nr '/ total/{N;N;s/( total\s*)?\n/ /gp}' file
于 2013-03-02T18:30:49.230 回答