sed
sur AIX ne fait pas ce que je pense qu'il devrait. J'essaie de remplacer plusieurs espaces par un seul espace dans la sortie d'IOSTAT:
# 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 doit rechercher et remplacer (s) plusieurs espaces (/ [] * /) par un seul espace (/ /) pour tout le groupe (/ g) ... mais ce n'est pas seulement cela ... son espacement pour chaque caractère.
Qu'est-ce que je fais mal? Je sais que ça doit être quelque chose de simple ... AIX 5300-06
edit: J'ai un autre ordinateur qui a plus de 10 disques durs. J'utilise ceci comme paramètre d'un autre programme à des fins de surveillance.
Le problème que j'ai rencontré était que "awk '{print $ 5}' ne fonctionnait pas parce que j'utilisais $ 1, etc. dans la phase secondaire et donnais des erreurs avec la commande Print. Je cherchais une version grep/sed/cut Ce qui semble fonctionner est:
iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5
Les [] s étaient "0 ou plus" quand je pensais qu'ils signifiaient "juste un". La suppression des supports l'a fait fonctionner. Trois très bonnes réponses rendent très rapidement difficile le choix de la "réponse".
L'utilisation de grep
est redondante, sed
peut faire de même. Le problème réside dans l'utilisation de *
qui correspondent également à 0 espace, vous devez utiliser \+
au lieu:
iostat | sed -n '/hdisk1/s/ \+/ /gp'
Si votre sed
ne prend pas en charge \+
metachar, alors faites
iostat | sed -n '/hdisk1/s/ */ /gp'
/[ ]*/
correspond à zéro ou plusieurs espaces, donc la chaîne vide entre les caractères correspond.
Si vous essayez de faire correspondre "un ou plusieurs espaces", utilisez l'un d'eux:
... | sed 's/ */ /g'
... | sed 's/ \{1,\}/ /g'
... | tr -s ' '
Change ton *
opérateur vers un +
. Vous correspondez à zéro ou plus du caractère précédent, ce qui correspond à chaque caractère parce que tout ce qui n'est pas un espace est ... euh ... zéro instance d'espace. Vous devez correspondre à UN ou plusieurs. En fait, il serait préférable de faire correspondre deux ou plusieurs
La classe de caractères entre crochets n'est pas non plus nécessaire pour faire correspondre un caractère. Vous pouvez simplement utiliser:
s/ \+/ /g
... à moins que vous ne vouliez également faire correspondre des tabulations ou d'autres types d'espaces, la classe de caractères est une bonne idée.
Vous pouvez toujours faire correspondre la dernière occurrence dans une séquence de quelque chose comme:
s/\(sequence\)*/\1/
Et vous êtes donc sur la bonne voie, mais plutôt que de remplacer la séquence par un espace - remplacez-la par sa dernière occurrence - un seul espace. De cette façon, si une séquence d'espaces est correspond alors la séquence est réduite à un seul espace, mais si la chaîne nulle est mise en correspondance, alors la chaîne nulle est remplacée par elle-même - et aucun mal, aucune faute. Ainsi, par exemple:
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
Cela dit, il vaut probablement mieux éviter complètement les regexps dans cette situation et faire à la place:
tr -s \ <infile
Notez que vous pouvez également faire ce que vous essayez, c'est-à-dire
iostat | grep "hdisk1 " | sed -e's/ */ /g' | cut -d" " -f 5
par
iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done
ce qui pourrait être particulièrement utile si vous essayez d'accéder ultérieurement à d'autres champs et/ou de calculer quelque chose - comme ceci:
iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done
Vous pouvez utiliser le script suivant pour convertir plusieurs espaces en un seul espace, un TAB ou toute autre chaîne:
$ 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"