it-swarm-tr.com

Sed kullanarak birden çok alanı nasıl şeritleyebilirim?

sed AIX üzerinde olması gerektiğini düşündüğüm şeyi yapmıyor. IOSTAT çıkışında tek bir boşluk ile birden çok boşluk yerine çalışıyorum:

# 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, tüm grubu (/ g) tek bir boşlukla (/ /) birden çok boşluk (/ [] * /) aramalı ve değiştirmelidir ... ama sadece bunu yapmakla kalmıyor ... her karakteri aralıklıyor.

Neyi yanlış yapıyorum? Basit bir şey olması gerektiğini biliyorum ... AIX 5300-06

edit: 10'dan fazla sabit diske sahip başka bir bilgisayarım var. Bu izleme amacıyla başka bir programa parametre olarak kullanıyorum.

Karşılaştığım sorun, "awk '{print $ 5}' 'ın ikincil aşamada $ 1, vb. Kullandığım ve Print komutuyla hatalar verdim çünkü bir grep/sed/cut sürümü arıyordum İşe yarayan şey:

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

"Sadece bir" anlamına geldiğini düşündüğümde [] ler "0 ya da daha fazla" idi. Parantezlerin çıkarılması işe yaradı. Üç çok iyi cevap gerçekten hızlı bir şekilde "cevap" seçmeyi zorlaştırır.

72
WernerCD

grep kullanımı gereksizdir, sed da aynısını yapabilir. Sorun * de 0 boşlukla eşleşiyorsa, \+ yerine:

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

sed öğeniz \+ metachar, sonra yap

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

/[ ]*/, sıfır veya daha fazla boşlukla eşleştiğinden, karakterler arasındaki boş dize eşleşir.

"Bir veya daha fazla boşluğu" eşleştirmeye çalışıyorsanız, aşağıdakilerden birini kullanın:

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

* operatörünü +. Önceki karakterin sıfırını veya daha fazlasını eşleştiriyorsunuz, bu her karakterle eşleşiyor çünkü boşluk olmayan her şey ... um ... sıfır boşluk örneğidir. ONE veya daha fazlasıyla eşleşmeniz gerekiyor. Aslında iki veya daha fazlasını eşleştirmek daha iyi olurdu

Köşeli ayraçlı karakter sınıfı da bir karakteri eşleştirmek için gerekli değildir. Sadece şunu kullanabilirsiniz:

s/  \+/ /g

... sekmeleri veya diğer boşluk türlerini de eşleştirmek istemiyorsanız, karakter sınıfı iyi bir fikirdir.

15
Caleb

Son olayı her zaman aşağıdaki gibi bir sırayla eşleştirebilirsiniz:

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

Ve böylece doğru yoldasınız, ancak diziyi bir boşlukla değiştirmek yerine - son ortaya çıkmasıyla değiştirin - tek bir boşluk. Bu şekilde bir boşluk dizisi is eşleşirse, dizi tek bir boşluğa indirgenir, ancak null dize eşleşirse null dize kendisiyle değiştirilir - ve zarar vermez, faul olmaz. Yani mesela:

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

ÇIKTI

# 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

Bütün bunlar, bu durumda normal ifadelerden tamamen kaçınmak ve bunun yerine yapmak muhtemelen daha iyidir:

tr -s \  <infile
8
mikeserv

Denediğinizi de yapabileceğinize dikkat edin.

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

tarafından

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

daha sonra başka alanlara da erişmeye ve/veya bir şey hesaplamaya çalışırsanız özellikle yararlı olabilir:

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

Birden çok boşluğu tek bir boşluğa, SEKME'ye veya başka bir dizeye dönüştürmek için aşağıdaki komut dosyasını kullanabilirsiniz:

$ 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