6

我可以使用如下命令在 vim 中搜索空翻译:

/""\n\n

但我的任务是查找未翻译字符串的数量。任何想法如何使用每个 linux 机器都应该拥有的标准工具来做到这一点(请不要单独的包)。

这是包含 2 个已翻译字符串和 2 个未翻译字符串(长和短变体)的 .po 文件示例。

msgid "translated string"
msgstr "some translation"

msgid "non-translated string"
msgstr ""

msgid ""
"Some long translated string which starts from new line "
"and can last for few lines"
msgstr ""
"Translation of some long string which starts from new line "
"and lasts for few lines"

msgid ""
"Some long NON-translated string which starts from new line "
"and can last for few lines"
msgstr ""
4

5 回答 5

7

这是一种使用方法awk

awk '$NF == "msgstr \"\"" { c++ } END { print c }' FS="\n" RS= file

结果:

2

解释:

进入awk段落模式。然后测试每个块中的最后一行。如果最后一行与模式完全匹配,则计算它。然后,在脚本的最后,打印出计数。如果您稍后决定要计算已翻译字符串的数量,只需更改==!=. HTH。


从下面的评论中,处理包含空格的空行:

您需要使用正则表达式,例如:(RS="\n{2,}|\n([ \t]*\n)+|\n$"这可能会被简化)。但是,应该注意的是,成为正则表达式的能力RSGNU awk扩展。Otherawk将无法以某种方式处理多字符记录分隔符。幸运的是,上述文件格式看起来相当严格,因此不需要处理包含空格的行。

如果遇到包含空格的分隔符,快速修复是调用sed

< file sed 's/^ *$//' | awk ...
于 2013-02-10T14:57:58.770 回答
6

我建议使用可用的gettext工具,而不是尝试.po直接解析文件:

$ msggrep -v -T -e "." test.po 
msgid "non-translated string"
msgstr ""

msgid ""
"Some long NON-translated string which starts from new line and can last for "
"few lines"
msgstr ""

msggrep标志是:

  • -v反转匹配
  • -T将下一个模式应用于msgstr
  • -e搜索模式

即显示任何msgstr不匹配/./的,因此是空的。

由于msggrep没有-c,单行中的计数为:

 msggrep -v -T -e "." test.po  | grep -c ^msgstr

(自 2002 年 1 月 v0.11 以来msggrep一直是gettext软件包的一部分。LSB 核心又名 ISO/IEC 23360-1:2006(E) 仅强制要求gettextmsgfmt二进制文件,但我还没有看到没有它的系统,所以它应该希望能满足你的要求。)

于 2013-02-13T16:47:46.307 回答
2

由于awk已经给出了(不错的)解决方案,因此还有其他 4方法:

所有命令都使用您的示例和一个好的.po文件进行了测试。

使用sed

sed -ne '/msgstr ""/{N;s/\n$//p}' <poFile | wc -l
2

解释:每次我找到msgstr "",我合并下一行,如果我可以将换行符作为字符串的最后一个字符s/\n$//,我打印它们p。最后计算行数。

仅重击

不使用 bash 以外的任何二进制文件:

total=0
while read line;do
    if [ "$line" == 'msgstr ""' ] ;then
        read line
        [ -z "$line" ] && ((total++))
      fi
  done <poFile
echo $total
2

解释:每次我找到msgstr ""时,我都会阅读下一行,如果为空,我会增加我的计数器。

其他 bash 方式
mapfile -t line <poFile
count=0
for ((i=${#line[@]};i--;));do
    [ -z "${line[i]}" ] && [ "${line[i-1]}" == 'msgstr ""' ] && ((count++))
  done
echo $count
2

解释:在一个数组中读取整个.po文件,而不是浏览数组以查找前一个字段包含的空字段msgstr "",递增计数器,而不是打印。

Perl(在命令行模式下)

perl -ne '$t++if/^$/&&$l=~/msgstr\s""\s*$/;$l=$_;END{printf"%d\n",$t}' <poFile
2

解释:每次我发现一个空行并且前一行(存储在变量中$l)包含msgstr ""然后我增加计数器。

破折号(不是 bash!)

count=0
while read line ; do
    [ "$line" = "" ] && [ "$prev" = 'msgstr ""' ] && true $((count=count+1))
    prev="$line"
  done <poFile
echo $count
2

基于 perl 示例,这适用于

于 2013-02-13T14:45:27.720 回答
1

尝试:

grep -c '^""$'

它计算唯一内容是两个“的行。

编辑:

根据您的评论,我发现上述内容不符合您的需求。要执行多行匹配,您可以按以下方式使用 GNU grep:

grep -Pzo '^msgstr ""\n\n' en.po | grep -c msgstr

使用 GNU grep 2.14 测试并发现它可以工作。但是,我不知道 GNU grep 对您来说是否足够标准。

第一个 grep 的解释:

-P激活 Perl 正则表达式扩展。

-z用 null 替换行尾的换行符,允许 grep 跟踪新行。

-oprint 'only-matching',需要,因为-z正在使用;否则我们会打印整个文件。

第二个grep的解释:

-c计算匹配的行数,在本例中为msgstr。这必须在单独的grep语句中,-c如果与 一起使用将返回 1 -z

于 2013-01-25T14:50:53.643 回答
-1
grep -n ^msg your.po | grep -v '""' | uniq -D -f1

这会查找以 开头的行msg,忽略那些只是空字符串 ( "") 的行,然后用于uniq查找重复的行(忽略msgid/msgstr字段)。

CUPS 文件的示例输出:

$ grep -n ^msg /usr/share/locale/es/cups_es.po | grep -v '""' | uniq -D -f1
3742:msgid "ParamCustominCutInterval"
3743:msgstr "ParamCustominCutInterval"
3745:msgid "ParamCustominTearInterval"
3746:msgstr "ParamCustominTearInterval"
3858:msgid "Quarto"
3859:msgstr "Quarto"
3967:msgid "Stylus Color Series"
3968:msgstr "Stylus Color Series"
3970:msgid "Stylus Photo Series"
3971:msgstr "Stylus Photo Series"
3973:msgid "Super A"
3974:msgstr "Super A"
于 2013-01-25T14:52:07.003 回答