我想用相同数量的 X 替换标签之间的值。例如
1.
<Name> Jason </Name>
to
<Name> XXXXX </Name>
2. (看没有空格)
<Name>Jim</Name>
to
<Name>XXX</Name>
3.
<Name Jason />
to
<Name XXXXX />`
4.
<Name Jas />
to
<Name XXX />
起始标记、值和结束标记都可以位于不同的行
5.
<Name>Jim
</Name>
to
<Name>XXX
</Name>
6.
<Name>
Jim
</Name>
to
<Name>
XXX
</Name>
7.
<Name
Jim
/>
to
<Name
XXX
/>
8.
<Name> Jason </Name> <Name> Ignacio </Name>
to
<Name> XXXXX </Name> <Name> XXXXXX </Name>
9.
<Name> Jason Ignacio </Name>
to
<Name> XXXXX XXXXXXX </Name>
or
<Name> XXXXXXXXXXXXX </Name>
两个都很好
我尝试了这个,但没有成功
file=mylog.log
search_str="<Name>"
end_str="</Name>"
sed -i -E ':a; s/('"$search_str"'X*)[^X'"$end_str"']/\1X/; ta' "$file"
请让我知道如何在 bash 脚本中执行此操作......
更新:
我也尝试过这个,但对 6 和 7 例不起作用。案例 1 至 5 有效。
sed -i -E '/<Name>/{:a; /<\/Name>/bb; n; ba; :b; s/(<Name>X*)[^X\<]/\1X/; tb; }' "$file"
sed -i -E '/<Name[[:space:]]/{:a; /\/>/bb; n; ba; :b; s/(<Name[[:space:]]X*)[^X\/]/\1X/; tb; }' "$file"
最佳答案
临时解决方案
这扩展了下面的“首次发行”并处理情况 1、2、5、6、8、9。它不处理有一个或多个完整 <Name>…</Name>
的情况。条目以及起始 <Name>
没有匹配的</Name>
在同一条线上。坦率地说,我什至不知道如何开始解决这种情况。
未处理的情况 3、4、7 不是有效的 XML — 我也不相信它们是有效的 HTML(或 XHTML)。我相信它们可以通过与此处显示的完整 <Name>…</Name>
类似(但更简单)的机制来处理。版本。我将其作为练习留给读者(注意字符类中的 <
— 它需要变成 /
)。
script.sed
/<Name>/! b
/<Name>.*<\/Name>/{
: l1
s/\(<Name>[[:space:]]*\(X[X[[:space:]]*\)\{0,1\}\)[^X<[:space:]]\(.*[[:space:]]*<\/Name>\)/\1X\3/
t l1
b
}
/<Name>/,/<\/Name>/{
# Handle up to 4 lines to the end-name tag
/<\/Name>/! N
/<\/Name>/! N
/<\/Name>/! N
/<\/Name>/! N
# s/^/ZZ/; s/$/AA/p
# s/^ZZ//; s/AA$//
: l2
s/\(<Name>[[:space:]]*\(X[X[[:space:]]*\)\{0,1\}\)[^X<[:space:]]\(.*[[:space:]]*<\/Name>\)/\1X\3/
t l2
}
第一行“跳过”不包含 <Name>
的行的处理(它们被打印并读取下一行)。接下来的 6 行是“首次发行”中的脚本,只不过有一个 b
跳转到处理结束。
新部分是/<Name>/,/<\/Name>/
代码。这寻找 <Name>
本身,并连接最多 4 行,直到 </Name>
包含在模式空间中。这两行注释用于调试——它们使我能够看到什么被视为一个单元。除非使用标签l2
代替l1
,其余部分与首次发行时完全相同 - sed
正则表达式已经适应换行符。
这是重型 sed
脚本而不是我想要使用或维护的内容。我会选择使用 XML 解析器的 Perl 解决方案(因为我比 Python 更了解 Perl),但使用适当的 XML 解析器,Python 也能很好地完成这项工作。
data
稍微扩展的数据文件。
<Name> Jason </Name>
<Name>Jim</Name>
<Name> Jason Bourne </Name>
<Name> Elijah </Name> <Name> Dennis </Name>
<Name> Elijah Wood </Name> <Name> Dennis The Menace </Name>
<Name>Elijah Wood</Name> <Name>Dennis The Menace</Name>
<Name> Jason
</Name>
<Name>
Jim</Name>
<Name>
Jim
</Name>
<Name> Jason
Bourne </Name>
<Name>
Jason
Bourne
</Name>
<Name> Elijah </Name>
<Name>
Dennis
</Name>
<Name> Elijah
Wood </Name>
<Name> Dennis
The Menace </Name>
<Name>Elijah
Wood</Name>
<Name>Dennis The
Menace</Name>
<Name> Jason </Name>
to
<Name> XXXXX </Name>
2. (see no space)
<Name>Jim</Name>
to
<Name>XXX</Name>
3.
<!--Name Jason /-->
to
<!--Name XXXXX /-->`
4.
<!--Name Jas /-->
to
<!--Name XXX /-->
starting tag, value and closing tag can all come in different line
5.
<Name>Jim
</Name>
to
<Name>XXX
</Name>
6.
<Name>
Jim
</Name>
to
<Name>
XXX
</Name>
7.
<!--Name
Jim
/-->
to
<!--Name
XXX
/-->
8.
<Name> Jason </Name> <Name> Ignacio </Name>
to
<Name> XXXXX </Name> <Name> XXXXXX </Name>
9.
<Name> Jason Ignacio </Name>
to
<Name> XXXXX XXXXXXX </Name>
or
<Name> XXXXXXXXXXXXX </Name>
没有声称data
文件包含最少的案例集;这是重复的。它包含问题中的 Material ,但“非正统”XML 元素(例如 <Name Value />
)除外。转换为 XML 注释 <!--Name Value /-->
。映射实际上并不重要;重要的是。开头部分不匹配<Name>
(并且尾部与 </Name>
不匹配),因此它们无论如何都不会被处理。
输出
$ sed -f script.sed data
<Name> XXXXX </Name>
<Name>XXX</Name>
<Name> XXXXX XXXXXX </Name>
<Name> XXXXXX </Name> <Name> XXXXXX </Name>
<Name> XXXXXX XXXX </Name> <Name> XXXXXX XXX XXXXXX </Name>
<Name>XXXXXX XXXX</Name> <Name>XXXXXX XXX XXXXXX</Name>
<Name> XXXXX
</Name>
<Name>
XXX</Name>
<Name>
XXX
</Name>
<Name> XXXXX
XXXXXX </Name>
<Name>
XXXXX
XXXXXX
</Name>
<Name> XXXXXX </Name>
<Name>
XXXXXX
</Name>
<Name> XXXXXX
XXXX </Name>
<Name> XXXXXX
XXX XXXXXX </Name>
<Name>XXXXXX
XXXX</Name>
<Name>XXXXXX XXX
XXXXXX</Name>
<Name> XXXXX </Name>
to
<Name> XXXXX </Name>
2. (see no space)
<Name>XXX</Name>
to
<Name>XXX</Name>
3.
<!--Name Jason /-->
to
<!--Name XXXXX /-->`
4.
<!--Name Jas /-->
to
<!--Name XXX /-->
starting tag, value and closing tag can all come in different line
5.
<Name>XXX
</Name>
to
<Name>XXX
</Name>
6.
<Name>
XXX
</Name>
to
<Name>
XXX
</Name>
7.
<!--Name
Jim
/-->
to
<!--Name
XXX
/-->
8.
<Name> XXXXX </Name> <Name> XXXXXXX </Name>
to
<Name> XXXXX </Name> <Name> XXXXXX </Name>
9.
<Name> XXXXX XXXXXXX </Name>
to
<Name> XXXXX XXXXXXX </Name>
or
<Name> XXXXXXXXXXXXX </Name>
$
首次发行
部分答案 - 但它说明了您面临的问题。处理问题中的情况 1 和 2,加上多词变体,您可以使用脚本:
script.sed
/<Name>.*<\/Name>/{
: l1
s/\(<Name>[[:space:]]*\(X[X[[:space:]]*\)\{0,1\}\)[^X<[:space:]]\(.*[[:space:]]*<\/Name>\)/\1X\3/
t l1
}
老实说,这相当扭曲。它寻找 <Name>
后跟零个或多个空格。后面可以是 \(X[X[[:space:]]*\)\{0,1\}
,这意味着 X 出现零次或一次,后跟一系列 X 或空格。所有这些都被捕获为 \1
在替换中。然后有一个字符不是 X
, <
或空格,后跟零个或多个任意字符、零个或多个空格以及 </Name>
。中间的单个字符被 X 替换。重复整个替换,直到通过标签 : l1
不再有匹配项为止。和条件分支 t l1
。所有这些都只在一条线上运行 <Name>
和</Name>
.
data
<Name> Jason </Name>
<Name>Jim</Name>
<Name> Jason Bourne </Name>
<Name> Elijah </Name> <Name> Dennis </Name>
<Name> Elijah Wood </Name> <Name> Dennis The Menace </Name>
<Name>Elijah Wood</Name> <Name>Dennis The Menace</Name>
<Name> Jason
</Name>
<Name>
Jim</Name>
<Name> Jason
Bourne </Name>
<Name> Elijah </Name> <Name> Dennis
</Name>
<Name> Elijah
Wood </Name> <Name> Dennis
The Menace </Name>
<Name>Elijah
Wood</Name> <Name>Dennis The
Menace</Name>
输出
$ sed -f script.sed data
<Name> XXXXX </Name>
<Name>XXX</Name>
<Name> XXXXX XXXXXX </Name>
<Name> XXXXXX </Name> <Name> XXXXXX </Name>
<Name> XXXXXX XXXX </Name> <Name> XXXXXX XXX XXXXXX </Name>
<Name>XXXXXX XXXX</Name> <Name>XXXXXX XXX XXXXXX</Name>
<Name> Jason
</Name>
<Name>
Jim</Name>
<Name> Jason
Bourne </Name>
<Name> XXXXXX </Name> <Name> Dennis
</Name>
<Name> Elijah
Wood </Name> <Name> Dennis
The Menace </Name>
<Name>Elijah
Wood</Name> <Name>Dennis The
Menace</Name>
$
注意最后的替换部分。这条线将会引起其他任何事情的头痛。
我还没有弄清楚脚本如何处理各种分行情况,除此之外几乎肯定需要连接行,直到 </Name>
被捕获了。然后,它将执行与已显示的内容密切相关的处理,但需要允许匹配 Material 中的换行符。
关于bash - 更改文件中两个带有字符 X 的字符串之间的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38911200/