Bash - 在文件中搜索特定字符串并替换为直接源
Bash - Search for a specific string in a file and replace with immediate source
我正在尝试在包含以下内容的文件中搜索字符串 "missing":
<message>
<source>TypeA</source>
<translation>missing</translation>
</message>
<message>
<source>TypeB</source>
<translation>missing</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>missing</translation>
</message>
如果找到 "missing",我想用它的直接源名称替换该字符串。例如:
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
到目前为止,我能够使用 awk 搜索字符串并打印直接源名称:
match([=13=], /<source>(.*)<\/source>/,n){ src=n[1] }
match([=13=], /<translation>(.*)<\/translation>/,s){ trs=s[1] }
/unfinished/{ print "Translation missing or incomplete for: '" trs "'","located inside source named: '" src "'" }
然后将其保存为 something.awk
使用以下方式调用它:
awk -f something.awk filelocation
但我不确定如何用源中的值替换字符串 "missing"。
任何人都可以建议我如何替换它吗?
你可以试试这个(写在something.awk):
{
if([=10=] ~ "<source>"){
source = gensub(/.*<source>(.*)<\/source>.*/, "\1", "", [=10=])
}
if([=10=] ~ "<translation>missing"){
[=10=] = gensub(/>.*</, ">" source "<", "", [=10=])
}
print
}
我不知道您是否需要特定版本的 awk 才能使用 gensub...(也许是 gawk?)。但是当我这样做时它可以在我的电脑上运行:
awk -f something.awk filelocation
结果:
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
正如我所说,如果不遵守标签的顺序(或者如果每行有多个标签,...),这可能是一个严重的问题。如果您在源和翻译之间有一个标签,这没什么大不了的,但源必须在翻译之前。如果不是这种情况,您可能需要使用正确的 XML 解析器工具(awk iksn't)解析您的文件,然后进行更改并打印到文件。
虽然你已经接受了答案,但我会添加这个。
在您的评论中,您告诉我们您的输入文件是格式正确的 xml 文档。所以我会以 xml 的方式处理它。我喜欢 awk/sed/grep,但我不得不说它们(和正则表达式)确实不是处理 xml 文件的正确工具,尽管它有时工作起来又快又脏。
有命令行工具:xsltproc
,可以通过xslt将xml文档转换成其他格式。
xslt也比较简单:(另存为f.xslt
)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="translation[.='missing']">
<xsl:copy>
<xsl:value-of select="../source"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
你需要做的只是:
xsltproc f.xslt input.xml
用你的输入文件测试一下:(我添加了一个根元素)
kent$ cat f.xml
<root>
<message>
<source>TypeA</source>
<translation>missing</translation>
</message>
<message>
<source>TypeB</source>
<translation>missing</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>missing</translation>
</message>
</root>
kent$ xsltproc f.xslt f.xml
<?xml version="1.0"?>
<root>
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
</root>
只要您的输入 xml 格式正确,这将始终有效。即使你在一行中输入 xml 或其他格式也可以。
您可以将输出用作变量并将其传递给 sed 进行替换,在我看来,简单使它变得完美,
sed s/'$AWK_RESULT/"REPALACE_STATE"/g'
在迭代孔文本期间,您也可以在循环中使用它。
我正在尝试在包含以下内容的文件中搜索字符串 "missing":
<message>
<source>TypeA</source>
<translation>missing</translation>
</message>
<message>
<source>TypeB</source>
<translation>missing</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>missing</translation>
</message>
如果找到 "missing",我想用它的直接源名称替换该字符串。例如:
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
到目前为止,我能够使用 awk 搜索字符串并打印直接源名称:
match([=13=], /<source>(.*)<\/source>/,n){ src=n[1] }
match([=13=], /<translation>(.*)<\/translation>/,s){ trs=s[1] }
/unfinished/{ print "Translation missing or incomplete for: '" trs "'","located inside source named: '" src "'" }
然后将其保存为 something.awk
使用以下方式调用它:
awk -f something.awk filelocation
但我不确定如何用源中的值替换字符串 "missing"。
任何人都可以建议我如何替换它吗?
你可以试试这个(写在something.awk):
{
if([=10=] ~ "<source>"){
source = gensub(/.*<source>(.*)<\/source>.*/, "\1", "", [=10=])
}
if([=10=] ~ "<translation>missing"){
[=10=] = gensub(/>.*</, ">" source "<", "", [=10=])
}
print
}
我不知道您是否需要特定版本的 awk 才能使用 gensub...(也许是 gawk?)。但是当我这样做时它可以在我的电脑上运行:
awk -f something.awk filelocation
结果:
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
正如我所说,如果不遵守标签的顺序(或者如果每行有多个标签,...),这可能是一个严重的问题。如果您在源和翻译之间有一个标签,这没什么大不了的,但源必须在翻译之前。如果不是这种情况,您可能需要使用正确的 XML 解析器工具(awk iksn't)解析您的文件,然后进行更改并打印到文件。
虽然你已经接受了答案,但我会添加这个。
在您的评论中,您告诉我们您的输入文件是格式正确的 xml 文档。所以我会以 xml 的方式处理它。我喜欢 awk/sed/grep,但我不得不说它们(和正则表达式)确实不是处理 xml 文件的正确工具,尽管它有时工作起来又快又脏。
有命令行工具:xsltproc
,可以通过xslt将xml文档转换成其他格式。
xslt也比较简单:(另存为f.xslt
)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="translation[.='missing']">
<xsl:copy>
<xsl:value-of select="../source"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
你需要做的只是:
xsltproc f.xslt input.xml
用你的输入文件测试一下:(我添加了一个根元素)
kent$ cat f.xml
<root>
<message>
<source>TypeA</source>
<translation>missing</translation>
</message>
<message>
<source>TypeB</source>
<translation>missing</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>missing</translation>
</message>
</root>
kent$ xsltproc f.xslt f.xml
<?xml version="1.0"?>
<root>
<message>
<source>TypeA</source>
<translation>TypeA</translation>
</message>
<message>
<source>TypeB</source>
<translation>TypeB</translation>
</message>
<message>
<source>TypeC</source>
<comment>Context menu</comment>
<translation>TypeC</translation>
</message>
</root>
只要您的输入 xml 格式正确,这将始终有效。即使你在一行中输入 xml 或其他格式也可以。
您可以将输出用作变量并将其传递给 sed 进行替换,在我看来,简单使它变得完美,
sed s/'$AWK_RESULT/"REPALACE_STATE"/g'
在迭代孔文本期间,您也可以在循环中使用它。