sed用XML属性中的破折号替换空间

时间:2021-01-05 16:52:28

I'm trying edit an xml file which has the following values

我正在尝试编辑一个具有以下值的xml文件

<item type="4" key="Port 1 Desc" value_type="1">
<item type="4" key="Port 1 InOctets" value_type="3">
<item type="4" key="Port 1 OutOctets" value_type="3">

I would like to eliminate the space and replce it with - my desired output would be like this:

我想消除这个空间,然后用-我想要的输出是这样的:

<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

Please keep in mind that number 1 is variable, and my xml file has port 2, 3 , 24 ..etc.

请记住,1是变量,我的xml文件有端口2、3、24等。

Thank you

谢谢你!

4 个解决方案

#1


1  

We prefer to use xml tool directly to handle xml file, such as in @Charles Duffy's reply.

Here is the way which only for this file, using awk.

这里是使用awk的方法。

awk  '{gsub(/ /,"-",$4)}1' FS=\" OFS=\" file

<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

Explaination

  • gsub(regexp, replacement [, target]) Search target for all of the longest, leftmost, nonoverlapping matching substrings it can find and replace them with replacement. The ‘g’ in gsub() stands for “global,” which means replace everywhere.
  • gsub(regexp, replace [, target])搜索目标,搜索它可以找到的所有最长、最左、最不重叠的匹配子字符串,并用替换替换它们。gsub()中的“g”代表“global”,意思是到处都可以替换。
  • FS=\" OFS=\" field separators
  • FS = \“OFS = \”字段分隔符
  • 1 same as print
  • 1打印一样

#2


2  

Using sed

使用sed

sed "{$(echo 's/ /-/3;'{,})}" file

$ cat file
<item type="4" key="Port 1 Desc" value_type="1">
<item type="4" key="Port 1 InOctets" value_type="3">
<item type="4" key="Port 1 OutOctets" value_type="3">

$ sed "{$(echo 's/ /-/3;'{,})}" file
<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

#3


2  

This approach requires XMLStarlet.

这种方法需要XMLStarlet。

It has the advantage of working as long as your XML is valid, rather than relying on the line-by-line formatting being exact, as many of the other answers here do.

只要XML是有效的,它就可以工作,而不是像这里的许多其他答案那样依赖逐行格式。

elem=
xmlstarlet pyx | while IFS='' read -r line; do
  if [[ $line = '('* ]]; then
    elem=${line:1}
    printf '%s\n' "$line"
  elif [[ $line = Akey* && $elem = item ]]; then
    value=${line#*" "}
    value=${line//" "/_}
    printf 'Akey %s\n' "$value"
  else
    printf '%s\n' "$line"
  fi
done | xmlstarlet depyx

#4


1  

Here is the single line solution using sed

这是使用sed的单行解决方案

sed 's/Port \([0-9]*\) /Port-\1-/g' filename

Note that, \1 is the remembered pattern.

注意,\1是记住的模式。

aman@apollo:~$ cat t

<item type="4" key="Port 1 Desc" value_type="1">
<item type="4" key="Port 1 InOctets" value_type="3">
<item type="4" key="Port 1 OutOctets" value_type="3">

aman@apollo:~$ sed 's/Port \([0-9]*\) /Port-\1-/g' t
<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

#1


1  

We prefer to use xml tool directly to handle xml file, such as in @Charles Duffy's reply.

Here is the way which only for this file, using awk.

这里是使用awk的方法。

awk  '{gsub(/ /,"-",$4)}1' FS=\" OFS=\" file

<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

Explaination

  • gsub(regexp, replacement [, target]) Search target for all of the longest, leftmost, nonoverlapping matching substrings it can find and replace them with replacement. The ‘g’ in gsub() stands for “global,” which means replace everywhere.
  • gsub(regexp, replace [, target])搜索目标,搜索它可以找到的所有最长、最左、最不重叠的匹配子字符串,并用替换替换它们。gsub()中的“g”代表“global”,意思是到处都可以替换。
  • FS=\" OFS=\" field separators
  • FS = \“OFS = \”字段分隔符
  • 1 same as print
  • 1打印一样

#2


2  

Using sed

使用sed

sed "{$(echo 's/ /-/3;'{,})}" file

$ cat file
<item type="4" key="Port 1 Desc" value_type="1">
<item type="4" key="Port 1 InOctets" value_type="3">
<item type="4" key="Port 1 OutOctets" value_type="3">

$ sed "{$(echo 's/ /-/3;'{,})}" file
<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">

#3


2  

This approach requires XMLStarlet.

这种方法需要XMLStarlet。

It has the advantage of working as long as your XML is valid, rather than relying on the line-by-line formatting being exact, as many of the other answers here do.

只要XML是有效的,它就可以工作,而不是像这里的许多其他答案那样依赖逐行格式。

elem=
xmlstarlet pyx | while IFS='' read -r line; do
  if [[ $line = '('* ]]; then
    elem=${line:1}
    printf '%s\n' "$line"
  elif [[ $line = Akey* && $elem = item ]]; then
    value=${line#*" "}
    value=${line//" "/_}
    printf 'Akey %s\n' "$value"
  else
    printf '%s\n' "$line"
  fi
done | xmlstarlet depyx

#4


1  

Here is the single line solution using sed

这是使用sed的单行解决方案

sed 's/Port \([0-9]*\) /Port-\1-/g' filename

Note that, \1 is the remembered pattern.

注意,\1是记住的模式。

aman@apollo:~$ cat t

<item type="4" key="Port 1 Desc" value_type="1">
<item type="4" key="Port 1 InOctets" value_type="3">
<item type="4" key="Port 1 OutOctets" value_type="3">

aman@apollo:~$ sed 's/Port \([0-9]*\) /Port-\1-/g' t
<item type="4" key="Port-1-Desc" value_type="1">
<item type="4" key="Port-1-InOctets" value_type="3">
<item type="4" key="Port-1-OutOctets" value_type="3">