我想将两个 sed 命令合并为一个,但真的不知道该怎么做,我尝试了多种方法但没有成功。
对于结果,我希望将特定标记之间的所有斜杠替换为反斜杠,这会导致:
来源 :
<FilePath>a/b/c/d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1/2/3/4</FilePath>
结果 :
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1\2\3\4</FilePath>
我发现这个命令可以更改标签之间的文本:
sed -i -e 's/\(<FilePath>\).*\(<\/FilePath>\)/<FilePath>TEXT_TO_REPLACE_BY<\/FilePath>/g' test.txt
但是这个命令替换了所有文本...所以我想要的是保留文本并且只使用这种命令用反斜杠替换斜杠:
sed -e 's/\\/\//g' test.txt
但我很难将这两者结合起来。
感谢您的帮助。
答案1
使用 GNU awk 将第三个参数匹配到 match():
awk 'match($0,/(.*<FilePath>)(.*)(<\/FilePath>.*)/,a){ gsub("/","\\",a[2]); $0=a[1] a[2] a[3] } 1' file
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob/Smith</OtherTags>
<FilePath>1\2\3\4</FilePath>
以上是使用以下输入运行的:
$ cat file
<FilePath>a/b/c/d</FilePath>
<OtherTags>Bob/Smith</OtherTags>
<FilePath>1/2/3/4</FilePath>
答案2
命令
sed -e 's/\//\\/g' -e 's/<\\/<\//g' filename
输出
<FilePath>a\b\c\d</FilePath>
<OtherTags>Bob</OtherTags>
<FilePath>1\2\3\4</FilePath>
答案3
使用扩展正则表达式模式的 GNU sed 我们可以逐步匹配在同一行上打开和关闭的 xml 标签 FilePath,并假设该标签不是引号或注释的一部分。
sed -Ee ' :a;s|<(FilePath)>([^/]*(/[^/]*)*)/([^/]*</\1>)|<\1>\2\\\4|;ta' file
perl -lpe '
s{<FilePath>\K.*?(?=</FilePath>)}
<$& =~ tr|/|\\|r>xge;
' file
我们隔离标签开始和结束之间的部分,并将其中的部分中的正斜杠转换为反斜杠。
我们可以编写多行正则表达式以便于表达意图。
snr='
s|
<(FilePath)>
( [^/]* ([/][^/]*)* )
/
( [^/]* )
</\1>
|<\1> \2 \\ \4 </\1>|
'
ws=$'\t \n'
sed -E ":a;${snr//[$ws]/};ta" file
答案4
这是一个相当简单的解决方案,使用 sed 和 tr 通过管道构建。它假设:
- 内部没有嵌套标签
<FilePath>…</FilePath>
(替换仅执行到下一个<
after<FilePath>
)。 <FilePath>
不出现在文字字符串内(no<![CDATA[<FilePath>/blah]]>
或<mytag label="<FilePath>">
)。- 即使最后一行没有终止换行符,您的 sed 实现也会正确处理它。
原理是使用tr
换行符<
和换行符;这样,当 sed 处理“行”时,它实际上是在处理一个打开/关闭标记和文本打开/关闭标记之间的文本。
tr '<\n' '\n<' | sed '/^FilePath>/ y:/:\\:' | tr '<\n' '\n<'
这是一个 Perl 解决方案。它假设:
- 里面没有嵌套标签
<FilePath>…</FilePath>
。 <FilePath>
不出现在文字字符串内(no<![CDATA[<FilePath>/blah]]>
或<mytag label="<FilePath>">
)。<FilePath>
后面总是</FilePath>
在同一行)。
构造相当自然:它将函数应用于backslashify
内的文本<FilePath>…</FilePath>
。正则表达式.*?
是非贪婪匹配:如果同一行上有多个块,则贪婪匹配.*
将替换该行中从第一个<FilePath>
到最后一个的所有内容。是一个更高级的版本,可以避免替换紧接在 之前或之后的斜杠,从而允许嵌套标签。</FilePath>
<FilePath>…</FilePath>
s:(?!<<)/(?!>):\\:
tr:/:\\:
>
<
perl -pe 'sub backslashify {local $_ = $_[0]; s:(?!<<)/(?!>):\\:; return $_} s:(<FilePath>)(.*?)(</FilePath>):$1.backslashify($2).$3:e'