sed
na AIX nedělá to, co si myslím, že by mělo. Ve výstupu IOSTAT se snažím nahradit více mezer jedním prostorem:
# 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 by měl hledat a nahradit více mezer (/ [] * /) jedním mezerou (/ /) pro celou skupinu (/ g) ... ale nedělá to jen to ... tím, že rozdělí jednotlivé znaky.
Co dělám špatně? Vím, že to musí být něco jednoduchého ... AIX 5300-06
edit: Mám další počítač, který má 10+ pevných disků. Používám to jako parametr pro jiný program pro účely monitorování.
Problém, na který jsem narazil, bylo to, že „awk“ {print $ 5} 'nefungovalo, protože používám $ 1 atd. V sekundární fázi a dával jsem chyby příkazem Print. Hledal jsem verzi grep/sed/cut Zdá se, že funguje:
iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5
[] Byly "0 nebo více", když jsem si myslel, že znamenají "jen jeden". Odstranění držáků to fungovalo. Tři velmi dobré odpovědi opravdu rychle ztěžují výběr „odpovědi“.
Použití grep
je nadbytečné, sed
může udělat totéž. Problém je v použití *
, které odpovídají také 0 mezerám, musíte použít \+
namísto:
iostat | sed -n '/hdisk1/s/ \+/ /gp'
Pokud váš sed
nepodporuje \+
metachar, pak ano
iostat | sed -n '/hdisk1/s/ */ /gp'
/[ ]*/
odpovídá nula nebo více mezer, takže prázdný řetězec mezi znaky odpovídá.
Pokud se snažíte shodovat „jeden nebo více mezer“, použijte jeden z těchto:
... | sed 's/ */ /g'
... | sed 's/ \{1,\}/ /g'
... | tr -s ' '
Změn svůj *
operátor k +
. Odpovídá nule nebo více předchozímu znaku, který odpovídá každé postavě, protože vše, co není mezerou, je ... um ... nula instancí prostoru. Musíte odpovídat jeden nebo více. Ve skutečnosti by bylo lepší srovnávat dva nebo více
Třída s hranatými znaky není také nutná pro přiřazení jednoho znaku. Stačí použít:
s/ \+/ /g
... pokud nechcete, aby odpovídaly karty nebo jiné druhy mezer, pak je třída znaků dobrý nápad.
Vždy se můžete shodovat s posledním výskytem v sekvenci:
s/\(sequence\)*/\1/
A tak jste na správné cestě, ale raději než nahrazení sekvence mezerou - nahrazením posledním výskytem - jediným mezerou. Pokud tedy dojde ke shodě posloupnosti mezer is, pak se posloupnost zmenší na jediný prostor, ale pokud se porovná nulový řetězec, nahradí se nulový řetězec sám sebou - a žádné poškození, žádná chyba. Například:
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
Vše, co bylo řečeno, je pravděpodobně mnohem lepší se v této situaci úplně vyhnout regexpsům a místo toho udělat:
tr -s \ <infile
Všimněte si, že můžete také dělat to, o co se pokoušíte
iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5
podle
iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done
což může být zvláště užitečné, pokud se později pokusíte také získat přístup k jiným polím a/nebo něco spočítat - například toto:
iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done
Následující skript můžete použít k převodu více mezer na jeden prostor, tabulku TAB nebo jakýkoli jiný řetězec:
$ 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
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"