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

Wer*_*rCD 88 sed aix text-processing

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
Run Code Online (Sandbox Code Playgroud)

sed 应该为整个组 (/g) 搜索和替换 (s) 多个空格 (/[ ]*/) 与单个空格 (//) ......但它不仅这样做......它的每个字符的间距。

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

编辑:我有另一台有 10 多个硬盘的计算机。我将此用作另一个程序的参数以进行监控。

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

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5
Run Code Online (Sandbox Code Playgroud)

当我认为 [] 的意思是“只有一个”时,[] 是“0 或更多”。卸下支架使其工作。三个非常好的答案真的很快让人很难选择“答案”。

gle*_*man 101

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

如果您尝试匹配“一个或多个空格”,请使用以下方法之一:

... | sed 's/  */ /g'
... | sed 's/ \{1,\}/ /g'
... | tr -s ' '
Run Code Online (Sandbox Code Playgroud)

  • +1 最简单的 `tr -s ' '` 解决方案 (12认同)
  • @WernerCD,没有`*` 使它成为“可选的”。`[ ]` 只是制作一个字符列表,其中只有一个字符(一个空格)。量词 `*` 表示“零个或多个先前的事物” (5认同)

enz*_*tib 69

使用grep是多余的,sed可以做同样的事情。问题是在使用*哪个也匹配0个空格。使用 GNU sed,您可以\+改用:

iostat | sed -n '/hdisk1/s/ \+/ /gp'
Run Code Online (Sandbox Code Playgroud)

或者,使用标准sed

iostat | sed -e '/hdisk/!d' -e 's/ \{2,\}/ /g'
Run Code Online (Sandbox Code Playgroud)

删除所有不包含 substring 的行hdisk,并用单个空格替换所有两个或多个空格的运行,或

iostat | sed -e '/hdisk1/!d' -e 's/   */ /g'
Run Code Online (Sandbox Code Playgroud)


Cal*_*leb 17

将您的*运营商更改为+. 您正在匹配零个或多个前一个字符,它匹配每个字符,因为所有不是空格的东西都是……​​嗯……空格的零个实例。您需要匹配一个或多个。其实两个或两个以上搭配会更好

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

s/  \+/ /g
Run Code Online (Sandbox Code Playgroud)

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

  • @userunknown:实际上我根本没有混合两件事,其他人都是:) 用单个空格替换单个空格是没有意义的,您只需要对至少有两个连续空格的匹配项执行此操作。两个空白和一个加号或三个空白和一个星号正是所需要的。 (3认同)

mik*_*erv 8

您始终可以匹配以下任何内容中的最后一次出现:

s/\(sequence\)*/\1/
Run Code Online (Sandbox Code Playgroud)

所以你在正确的轨道上,而不是用空格替换序列 - 用它的最后一次替换它 - 单个空格。这样,如果空格序列匹配的,则顺序减少到一个单一的空间,但如果空字符串匹配,则空字符串替换本身-而没有坏处,没有犯规。因此,例如:

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
Run Code Online (Sandbox Code Playgroud)

输出

# 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
Run Code Online (Sandbox Code Playgroud)

综上所述,在这种情况下完全避免使用正则表达式可能要好得多,而是这样做:

tr -s \  <infile
Run Code Online (Sandbox Code Playgroud)

  • +1 为简单起见,`iostat | tr -s \` (4认同)

roz*_*acz 5

请注意,您也可以执行您尝试的操作,即

iostat | grep "hdisk1 " | sed -e's/  */ /g' | cut -d" " -f 5
Run Code Online (Sandbox Code Playgroud)

经过

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$re"; done
Run Code Online (Sandbox Code Playgroud)

如果您以后也尝试访问其他字段和/或计算某些内容,这可能特别有用 - 如下所示:

iostat | while read disk tma kbps tps re wr; do [ "$disk" = "hdisk1" ] && echo "$(( re/1024 )) Mb"; done
Run Code Online (Sandbox Code Playgroud)