web-dev-qa-db-ja.com

sedを使用して複数のスペースを1つに取り除く方法は?

AIXでのsedは、私が思っていることを実行していません。 IOSTATの出力で、複数のスペースを1つのスペースに置き換えようとしています。

# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty:      tin         tout    avg-cpu: % user % sys % idle % iowait
          0.2         31.8                9.7   4.9   82.9      2.5

Disks:        % tm_act     Kbps      tps    Kb_read   Kb_wrtn
hdisk9           0.2      54.2       1.1   1073456960  436765896
hdisk7           0.2      54.1       1.1   1070600212  435678280
hdisk8           0.0       0.0       0.0          0         0
hdisk6           0.0       0.0       0.0          0         0
hdisk1           0.1       6.3       0.5   63344916  112429672
hdisk0           0.1       5.0       0.2   40967838  98574444
cd0              0.0       0.0       0.0          0         0
hdiskpower1      0.2     108.3       2.3   2144057172  872444176

# iostat | grep hdisk1
hdisk1           0.1       6.3       0.5   63345700  112431123

#iostat|grep "hdisk1"|sed -e"s/[ ]*/ /g"
 h d i s k 1 0 . 1 6 . 3 0 . 5 6 3 3 4 5 8 8 0 1 1 2 4 3 2 3 5 4

sedは、グループ全体(/ g)について、複数のスペース(/ [] * /)を検索して単一のスペース(/ /)に置き換えます(ただし、それだけではありません...各文字の間隔)。

何が悪いのですか?私はそれが何か単純なものであることを知っています... AIX 5300-06

編集: 10台以上のハードドライブを搭載した別のコンピュータを使用しています。これを監視目的で別のプログラムのパラメーターとして使用しています。

私が遭遇した問題は、「awk '{print $ 5}'が機能しなかったということです。セカンダリステージで$ 1などを使用していて、Printコマンドでエラーが発生しました。grep/ sed/cutバージョンを探していました。 。動作しているようです:

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5

「1つ」を意味すると思ったとき、[]は「0以上」でした。ブラケットを外すと機能します。 3つの非常に良い答えは、すぐに「答え」を選択するのを難しくします。

72
WernerCD

grepの使用は冗長です。sedでも同じことができます。問題は、0のスペースにも一致する*の使用にあります。代わりに\+を使用する必要があります。

iostat | sed -n '/hdisk1/s/ \+/ /gp'

sed\+メタ文字をサポートしていない場合は、

iostat | sed -n '/hdisk1/s/  */ /gp'
57
enzotib

/[ ]*/zero以上のスペースに一致するため、文字間の空の文字列が一致します。

「1つ以上のスペース」に一致させる場合は、次のいずれかを使用します。

... | sed 's/  */ /g'
... | sed 's/ \{1,\}/ /g'
... | tr -s ' '
75
glenn jackman

*演算子から+。スペースではないすべてのものが... um ...スペースのゼロインスタンスであるため、前の文字の0個以上に一致します。これはすべての文字に一致します。 1つ以上一致する必要があります。実際には2つ以上を一致させる方が良いでしょう

大括弧で囲まれた文字クラスも、1つの文字を突き合わせるために不要です。あなたはただ使うことができます:

s/  \+/ /g

...タブや他の種類のスペースにも一致させたい場合を除き、文字クラスは良い考えです。

15
Caleb

次のようなシーケンスの最後の出現と常に一致させることができます。

s/\(sequence\)*/\1/

そして、あなたは正しい軌道に乗っていますが、シーケンスをスペースで置き換えるのではなく、それを最後に出現したスペース1つに置き換えます。このようにして、スペースのシーケンスisが一致した場合、シーケンスは単一のスペースに削減されますが、null文字列が一致した場合、null文字列はそれ自体に置き換えられます-害やファウルはありません。したがって、たとえば:

sed 's/\( \)*/\1/g' <<\IN                                    
# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty:      tin         tout    avg-cpu: % user % sys % idle % iowait
          0.2         31.8                9.7   4.9   82.9      2.5

Disks:        % tm_act     Kbps      tps    Kb_read   Kb_wrtn
hdisk9           0.2      54.2       1.1   1073456960  436765896
hdisk7           0.2      54.1       1.1   1070600212  435678280
hdisk8           0.0       0.0       0.0          0         0
hdisk6           0.0       0.0       0.0          0         0
hdisk1           0.1       6.3       0.5   63344916  112429672
hdisk0           0.1       5.0       0.2   40967838  98574444
cd0              0.0       0.0       0.0          0         0
hdiskpower1      0.2     108.3       2.3   2144057172  872444176

# iostat | grep hdisk1
hdisk1           0.1       6.3       0.5   63345700  112431123

IN

出力

# iostat
System configuration: lcpu=4 drives=8 paths=2 vdisks=0

tty: tin tout avg-cpu: % user % sys % idle % iowait
 0.2 31.8 9.7 4.9 82.9 2.5

Disks: % tm_act Kbps tps Kb_read Kb_wrtn
hdisk9 0.2 54.2 1.1 1073456960 436765896
hdisk7 0.2 54.1 1.1 1070600212 435678280
hdisk8 0.0 0.0 0.0 0 0
hdisk6 0.0 0.0 0.0 0 0
hdisk1 0.1 6.3 0.5 63344916 112429672
hdisk0 0.1 5.0 0.2 40967838 98574444
cd0 0.0 0.0 0.0 0 0
hdiskpower1 0.2 108.3 2.3 2144057172 872444176

# iostat | grep hdisk1
hdisk1 0.1 6.3 0.5 63345700 112431123

そうは言っても、この状況では正規表現を完全に回避し、代わりに行う方がおそらくはるかに良いでしょう。

tr -s \  <infile
8
mikeserv

あなたがしようとすることもできることに注意してください、つまり

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5

沿って

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done

これは、後で他のフィールドにアクセスしたり、何かを計算したりする場合に特に便利です-このように:

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done
5
rozcietrzewiacz

次のスクリプトを使用して、複数のスペースを1つのスペース、TAB、またはその他の文字列に変換できます。

$ ls | compress_spaces.sh       # converts multiple spaces to one
$ ls | compress_spaces.sh TAB   # converts multiple spaces to a single tab character
$ ls | compress_spaces.sh TEST  # converts multiple spaces to the phrase TEST
$ compress_spaces.sh help       # show the help for this command

compress_spaces.sh

function show_help()
{
  IT=$(CAT <<EOF

  usage: {REPLACE_WITH}

  NOTE: If you pass in TAB, then multiple spaces are replaced with a TAB character

  no args -> multiple spaces replaced with a single space
  TAB     -> multiple spaces replaced with a single tab character
  TEST    -> multiple spaces replaced with the phrase "TEST"

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show help if we're not getting data from stdin
if [ -t 0 ]; then
  show_help
fi

REPLACE_WITH=${1:-' '}

if [ "$REPLACE_WITH" == "tab" ]
then
  REPLACE_WITH=$'\t'
fi
if [ "$REPLACE_WITH" == "TAB" ]
then
  REPLACE_WITH=$'\t'
fi

sed "s/ \{1,\}/$REPLACE_WITH/gp"
0
Brad Parks