it-swarm.cn

如何使用sed剥离多个空格?

sed在AIX上没有执行我认为应该做的事情。我正在尝试在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应该为整个组(/ g)搜索并用单个空格(/ /)替换多个空格(/ [] * /),但不仅是这样,它还分隔了每个字符。

我究竟做错了什么?我知道它一定很简单... AIX 5300-06

edit:我有一台装有10多个硬盘的计算机。我将此作为另一个程序的参数进行监视。

我遇到的问题是“ awk'{print $ 5}'不起作用,因为我在第二阶段使用了$ 1等,并给出了Print命令错误。我正在寻找grep/sed/cut版本。似乎有效的是:

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

当我以为[]等于“仅一个”时,它们是“ 0或更多”。卸下支架即可正常工作。三个非常好的答案确实很快使选择“答案”变得困难。

72
WernerCD

grep的使用是多余的,sed可以这样做。问题出在使用*也匹配0个空格,则必须使用\+代替:

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

如果您的sed不支持\+ metachar,然后执行

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

/[ ]*/匹配或更多空格,因此字符之间的空字符串匹配。

如果您要匹配“一个或多个空格”,请使用以下一项:

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

改变你的 *运算符到+。您要匹配零个或多个前一个字符,后者匹配每个字符,因为不是空格的所有内容都是... um ...零个实例。您需要匹配一个或多个。实际上,匹配两个或多个会更好

括号中的字符类对于匹配一个字符也是不必要的。您可以使用:

s/  \+/ /g

...除非您也想匹配制表符或其他类型的空格,否则字符类是一个好主意。

15
Caleb

您始终可以按以下顺序匹配最后一次出现:

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

因此,您处在正确的轨道上,而不是将序列替换为空格-将其替换为最后一个出现-单个空格。这样,如果空格序列is匹配,那么该序列将减少为单个空格,但是如果匹配空字符串,则将空字符串替换为其自身-不会造成伤害,也不会犯规。因此,例如:

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

您可以使用以下脚本将多个空格转换为单个空格,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