【问题标题】:How to increment a string variable within a for loop如何在for循环中增加字符串变量
【发布时间】:2016-10-20 00:26:28
【问题描述】:

我想要一个循环,它可以找到以多种语言最频繁地结束单词的字母,并以列的形式输出数据。 到目前为止我有

count="./wordlist/french/fr.txt ./wordlist/spanish/es.txt ./wordlist/german/de.$
lang="French Spanish German Portuguese Italian"
(
echo -e "Language Letter Count"
for i in $count
do
    (for j in {a..z}
        do
            echo -e "LANG" $j $(grep -c $j\> $i)
        done
    ) | sort -k3 -rn | head -1
done
) | column -t

我希望它如图所示输出:


Language  Letter  Count
French     e       196195
Spanish    a       357193
German     e       251892
Portuguese a       217178
Italian    a       216125

相反,我得到:


Language  Letter  Count
LANG      z       0
LANG      z       0
LANG      z       0
LANG      z       0
LANG      z       0

单词文件具有以下格式: Word Freq(#),其中单词及其频率由空格分隔。

这意味着我有 2 个问题; 首先,grep 命令没有处理参数$j\> 来查找单词末尾的字符。我尝试过使用grep -E $j\>grep '$j\>',但都没有成功。

第二个问题是我不知道如何输出语言的名称(在变量lang中)。当我这样尝试(或 i 和 k 以相反的顺序)时,嵌套另一个 for 循环不起作用:


(
for i in $count
do
    for k in $lang
    do
        for j in {a..z}
        do
             echo -e $k $j $(grep -c $j\> $i)
        done
        ) | sort -k3 -rn | head -1
done
done
) | column -t

因为这会在不属于它的地方输出语言名称“$k”的倍数。

我知道我可以为每种语言复制和粘贴循环,但我想将它扩展到每种语言。 提前致谢!

【问题讨论】:

  • 你能从两个单词列表文件中粘贴几行来测试吗?
  • 即使这样,它不会输出错误的数字吗?例如如果您的字数统计文件包含三个条目:is 1000; xertz 1; showbiz 1;,则结果将是 z 2(而不是s 1000
  • 是的,变音符号,它会 z 2 这是我想要的,因为我想计算频率并显示文件本身中最常结束单词的字符。而且,roelofs,此处显示了该文件的示例:de 1622928 je 1622619 est 1348809 pas 1128894 le 1093232 因此,在该文件本身中,e 最常以单词结尾。很抱歉造成误解。

标签: bash for-loop grep


【解决方案1】:

grep字边界

为了使特殊分隔符(例如,\> 用于 word-end)在从 shell 调用时与 egrep 一起使用,您应该将它们放入 "quotes"

 count=$(egrep -c "${char}\>" "${file}")

顺便说一句,你真的应该使用 双引号 ("),因为单引号会阻止变量扩展。 (例如在j="foo"; k='$j\>'中,k的值的第一个字符将是$而不是f

语言名称显示

获取正确的语言字符串有点棘手;这里有一些建议:

  • 从词表的路径导出显示的语言:

    lang=${file%/*}
    lang=${lang##*/}
    

    使用 bash(尽管不使用 dash 和其他一些 shell)你甚至可以使用 lang=${lang^} 来将字符串大写。

  • 在字典中查找正确的语言名称。 Bash-4 内置了字典,但你也可以使用基于文件的字典:

    $ cat languagues.txt
    ./wordlist/french/fr.txt Français 
    ./wordlist/english/en.txt English
    ./wordlist/german/de.txt Deutsch
    
    $ file=./wordlist/french/fr.txt
    $ lang=$(egrep "^${file}/>" languages.txt | awk '{print $2}')
    
  • 您还可以迭代 file,lang 对,例如

    languages="french/fr,French spanish/es,Español german/de,Deutsch"
    for l in $languages; do
       file=./wordlist/${l%,*}.txt
       lang=${l#*,}
       # ...
    done
    

考虑词频

我看到的第三个问题(尽管我可能误解了这个问题)是您没有考虑词频。例如使用频率比单词 B 多 1000 倍的单词 A 只会被计算一次(就像 B 一样)。

可以使用awk来总结匹配词的词频:

count=$(egrep "${char}\>" "${file}" | awk '{s+=$2} END {print s}')

现在都在一起

因此,问题的完整解决方案可能如下所示:

languages="french/fr,French spanish/es,Español german/de,Deutsch"

(
echo -e "Language Letter Count"
for l in ${languages}; do
  file=./wordlist/${l%,*}.txt
  lang=${l#*,}

  for char in {a..z}; do
     #count=$(egrep -c "${char}\>" "${file}")
     count=$(egrep "${char}\>" "${file}" | awk '{s+=$2} END {print s}')
     echo ${file} ${char} ${count}
  done | sort -k3 -rn | head -1
done
) | column -t

【讨论】:

  • 效果非常好,我学到了一些新东西,感谢 Umlaute!
  • 如果您不介意,我确实有一个问题,您能告诉我您是如何使用${l%,*}${l#*,} 的吗?我仍然对脚本中%# 的使用感到困惑,它们到底是什么意思?
  • @Angelo man bash 并搜索 ## 应该会给你一个比我能说的更好的解释。
猜你喜欢
  • 1970-01-01
  • 2017-01-26
  • 2013-11-25
  • 2011-02-24
  • 1970-01-01
  • 2015-04-15
  • 2011-11-24
  • 1970-01-01
相关资源
最近更新 更多