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」には、コンピューターのホスト名がそれぞれ別の行に含まれています。このコマンドは、ルート ユーザーのラボ マシンへのパスワードなしのログインで構成されたサーバーから実行されます。ファイル 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

サンプルデータを少し変更しました。

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)を使用して、5行の各セットのどこにいるかを把握していることです。

セットごとに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 に答える
1

これを試して:

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

trコマンドによるパイプ出力

trコマンドを介して出力をパイプするなど、より簡単な解決策を試すことができます。例えば:

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

ただし、これはファイルに 1 つのレコードしかないことを前提としています。複数のレコードを持つことを計画している場合は、出力ファイルに追加する前に、最初にtrパイプラインを介して各レコードをフィルター処理する必要があります。例えば:

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

Perl の Flip-Flop 演算子を使用する

複数行のレコードのセットがある場合は、より賢くする必要があります。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 に答える
0

レコード間に空の行がない場合は、最初に 1 つ導入できます。

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 に答える