【问题标题】:escaping in awk and bash script在 awk 和 bash 脚本中转义
【发布时间】:2016-06-10 23:51:39
【问题描述】:

我正在尝试更改文件第 2、3 和 4 列中的数字。为此,我有以下脚本

for i in 0.8 0.9 1 1.1 1.2; do
original=10.9398135077
fraction=`bc <<< "$i*$original"`
convert=0.529177
awk '{printf "%-2s %10.5f %10.5f %10.5f\n", $1, ($2*"\$fraction"*"\$convert"), ($3*"\$fraction"*"\$convert"), ($4*"\$fraction"*"\$convert")}' temp2_${i}.txt > coord_${i}.txt
done

我的 temp2_0.8.txt 如下所示:

Cu      -0.000000000   0.000000000  -0.000000000
Cu       0.500000000  -0.000000000   0.500000000
Cu       0.000000000   0.500000000   0.500000000
Cu       0.500000000   0.500000000   0.000000000
S        0.398420013   0.398420013   0.398420013
S        0.898420013   0.398420013   0.101579987
S        0.398420013   0.101579987   0.898420013
S        0.101579987   0.898420013   0.398420013
S        0.601579987   0.601579987   0.601579987
S        0.898420013   0.101579987   0.601579987
S        0.101579987   0.601579987   0.898420013
S        0.601579987   0.898420013   0.101579987

但如果我执行我的脚本,我会收到以下消息:

awk: warning: escape sequence `\$' treated as plain `$'

我在所有转换后的文件中都得到 0.00000。似乎我未能在 awk 中转义关键字......如何正确地将“分数”和“转换”乘以 awk 列号 2、3 和 4?

添加:) 我使用 \$fraction 而不是“\$fraction”,但它给了我错误“反斜杠不是最后一个字符”

【问题讨论】:

  • 在单引号内,shell 会忽略美元和反斜杠——只有单引号是有趣的。 awk 脚本因此得到错误的值。使用-v variable="$value" 将shell 变量传递给脚本。为什么要打扰bcawk 可以很开心地繁殖。
  • @JonathanLeffler 哇,谢谢,-v 有效~!这比我预期的要简单得多。我使用 bc 的原因是在 bash 脚本中乘以 $i 值,以便在脚本的不同部分使用它。但我认为你的想法也很好:) 谢谢

标签: bash awk escaping


【解决方案1】:

在单引号内,shell 会忽略美元、反斜杠、双引号、反引号——只有单引号是有趣的。 awk 脚本因此得到错误的值。使用-v variable="$value" 将shell 变量传递给脚本。为什么要打扰bcawk 可以很开心地繁殖。

original=10.9398135077
convert=0.529177
for i in 0.8 0.9 1 1.1 1.2
do
    awk -v org="$original" -v factor="$i" -v conv="$convert" \
        'BEGIN { multiplier = factor * original * convert }
         { printf "%-2s %10.5f %10.5f %10.5f\n", $1,
                  ($2 * multiplier),
                  ($3 * multiplier),
                  ($4 * multiplier) }' temp2_${i}.txt > coord_${i}.txt
done

【讨论】:

  • 非常感谢~!
【解决方案2】:

您不需要 shell 循环:

awk '
BEGIN {
    original = 10.9398135077
    convert = 0.529177
    split("0.8 0.9 1 1.1 1.2", factors)
    for (i in factors) {
        ARGV[i] = "temp2_"i".txt"
        outfiles[i] = "coord_"i".txt"
        multipliers[i] = factors[i] * original * convert
        ARGC++
    }
}
{
    printf "%-2s %10.5f %10.5f %10.5f\n", $1,
        $2 * multipliers[ARGIND],
        $3 * multipliers[ARGIND],
        $4 * multipliers[ARGIND] > outfiles[ARGIND]
}
'

如果您不使用 GNU awk,请在 BEGIN{...} 部分之后添加 FNR==1{ARGIND++} 语句。

【讨论】:

    猜你喜欢
    • 2019-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    相关资源
    最近更新 更多