file.txt
最も簡単な形式で、次の自動生成ファイルがあるとしますfile.txt
。
Source Destination Maximum To Maximum From Average Total Average To Average From
(192.168.1.1) (192.168.1.2) 202.89 Kbps 0 bps 645 bps 645 bps 0 bps
column
私はこのコマンドをいくつかのバリエーションで試しましたが、役に立ちませんでした。この出力を次のように作成するにはどうすればよいですか?
Source Destination Maximum To Maximum From Average Total Average To Average From
(192.168.1.1) (192.168.1.2) 202.89 Kbps 0 bps 645 bps 645 bps 0 bps
これを行う方法を知る必要があるようですが、空白を描いていますが、これまで期待どおりに機能している項目が見つかりませんでした。
編集する:以下の説明と回答はsed
元の例と完全に一致しています。 (私は実際には説明の解決策がより簡単でパイピングを含まないので好みますtr
。)つまり、両方の解決策は複数行ファイルでまったく同じパフォーマンスを発揮します。これには、file.txt
さまざまな長さの数百行のIPv4アドレスが含まれます。sed
これまでのところ、両方のソリューションは元のものよりも正確な結果を次のように返しますfile.txt
。
ソースファイル.txt:
Source Destination Maximum To Maximum From Average Total Average To Average From
(10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps
(10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps
(192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
更新されたfile.txt(これまで提案されたソリューションを使用した後):
Source Destination Maximum To Maximum From Average Total Average To Average From
(10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps
(10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps
(192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
このオフセット警告を解決するための更新されたソリューションはありますか?
答え1
スクリプトはOPのサンプルデータに基づいています。
sed '
s/\s\s\+/:/g
s/\([a-z)]\)\s\([(0-9A]\)/\1:\2/g
' file.txt |
column -s: -t
- 見つけやすい区切り文字を変更して始めます(
\s
手順2以降)。:
- 2番目のステップでは、残りの可能な区切り文字を探します。
- 小文字と数字の間
- 後ろに
)
- 今後
A
- 列区切り文字を使用した文字列の書式設定
:
答え2
次のPerlスクリプトは、最初の2つのフィールドにそれぞれ1つの「単語」があり、残りのフィールドには2つの「単語」があるという知識に基づいて、入力をタブ区切りフィールドに変換します。その後、出力は次にパイプされます。column -s $'\t' -t
これはやや不器用で無差別的なアプローチですが、うまくいきます。
#! /usr/bin/perl
use strict;
while(<>) {
my (@F, @fields, $i);
@F=split;
$fields[0] = $F[0] ;
$fields[1] = $F[1] ;
for $i (0..4) {
$fields[$i + 2] = $F[$i*2 + 2] . ' ' . $F[$i*2 + 3];
}
print join("\t",@fields),"\n";
}
使用方法は次のとおりです。
$ ./bandwidth.pl bandwidth.txt | column -s $'\t' -t
Source Destination Maximum To Maximum From Average Total Average To Average From
(10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps
(10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps
(192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
これは、区切りフィールドに区切り文字(スペースなど)を使用することが決して良い考えではない理由を示す良い例です。これは必要以上に状況をより困難にするだけであり、ファイルの内容と構造に関する事前の知識がなければ、区切り文字とフィールドの内容を区別するための信頼できる方法はありません。
答え3
修正する:次の例では、名前付きソース全体のコピーを使用してくださいfull_original.txt
。
$ sed 's/\((\)/ \1/g;s/\(Average\)/ \1/g;s/ \([0-9]\)/ \1/g;s/\(\S\) \(\S\)/\1_\2/g' full_original.txt | column -t | tr _ ' '
Source Destination Maximum To Maximum From Average Total Average To Average From
(10.10.10.21) (192.168.123.122) 18.90 Kbps 0 bps 131 bps 131 bps 0 bps
(10.10.10.22) (192.168.123.122) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(10.10.10.23) (192.168.123.123) 10.88 Kbps 0 bps 23 bps 23 bps 0 bps
(192.168.123.123) (192.52.168.123) 0 bps 22.84 Kbps 1.17 Kbps 0 bps 1.17 Kbps
(192.168.123.124) (192.52.168.123) 0 bps 10.87 Kbps 19 bps 0 bps 19 bps
説明する
このソリューションの多くは、いくつかの個別の問題があり、それらを個別に解決する「分割と征服」アプローチに従います。最後に、仕上げタッチのための魔法命令でcolumn
組み立てられますtr
。
- Greedy / Globalの場合はデフォルトのパターンであるため、最初の一致だけ
s/searchstring/replacestring/g'
でg
なくすべての一致にも適用されます。 - グループ化を使用しているため、検索セクションで「最初のグループの場合」、「2番目のグループの場合」などで再
\(somegroup\)
印刷できます。\1
\2
- セミコロンを使用すると、パイプよりも効率的に
;
複数の検索および置換コマンドを単一のインスタンスに配置できるsed
ため、複数のsedを実行できますsed command | sed command | sed command ....
。 s/\((\)/ \1/g
...123) (19...
OPが検出したオフセットの問題を避けるために、括弧で囲まれた2つのIP値を2つ以上のスペースで押し出す操作を処理します。左角かっこを一致させ、(
前にスペースを付けてこれを行いますspace
。(
s/\(Average\)/ \1/g
特に別個の部品がないため、Maximum From Average Total
後で見つけて交換するのが難しくなる問題を解決するために、最初は各項目の前に追加のスペースを追加しました。Average
s/ \([0-9]\)/ \1/g
645 bps 645 bps 0 bps
発生前にスペースを追加してspace+number
元のテキストのフィールド値を分離すると、space+space+number
後続のsedコマンドがそれを区別するのに役立ちます。- 最後のsedコマンド
s/\(\S\) \(\S\)/\1_\2/g
は回避策で、non-space+space+non-space
スペースが下線になるようにグループ化して検索して変更します。これはMaximum To
後でcolumn
使用するコマンドのために一緒に保持されます。Maximum_To
| column -t
これを列コマンドにパイプすると、デフォルトでは次のようにman column
表示されます。By default, the column command will merge multiple adjacent delimiters into a single delimiter when using the -t option
したがって、テキスト間の可変スペースを単一の区切り文字として扱います。- 列は、テキストの並べ替えのために書式の再指定も実行します。
| tr _ ' '
最後に、空白をアンダースコア()に変換コマンドを使用して解決策を元に戻し、すべてを空白に戻します。_
tr
_
' '
これにより、目的の出力を得ることができます。