【问题标题】:Is there a cleaner way to add "else if" to assignment conditional in Awk, etc.?有没有一种更简洁的方法可以将“else if”添加到 Awk 等中的条件赋值?
【发布时间】:2011-04-12 08:39:06
【问题描述】:

某些语言(如 awk 脚本)允许条件赋值。例如,假设您有一个格式为的列表文件:

<item name, no spaces> <price as float>

例如

Grape 4.99
JuicyFruitGum 0.45
Candles 5.99

您想对超过 1 美元的所有商品征税...您可以使用 awk 脚本:

awk '{a=($2>1.00)?$2*1.06:$2; print a}' prices.data

...使用条件赋值来缩短语法。

但是假设您还想为所有超过 20 美元的商品提供 1 美元的折扣,超过 40 美元的商品也可以享受 2 美元的折扣。好吧,在像 c 这样的语言中,您通常会执行以下操作:

if (price > 40.00) {
   price-=2; 
   price *= 1.06; 
}
else if ( price > 20.00 && price <= 40.00 ) {
   price--; 
   price *= 1.06; 
}
else if ( price > 1.00 ) {
   price*=1.06;
}

...好吧,我发现您可以将 awk 或其他脚本语言混杂到 COMPOUND 分配中。例如:

awk '{a=($2>1.00)?($2>20.00)?($2-1)*1.06:($2>40.00)?($2-2)*1.06:$2*1.06:$2; print a}' prices.data

我的问题是

a) 是复合赋值(像这样)通常与支持条件赋值的脚本语言普遍兼容?
b) 在 awk 脚本中是否有一种非杂乱无章的方式来进行多条件赋值?

澄清一下:我只是在谈论赋值的简写(<...>?<...>:<...>;,而不是传统的条件赋值,我已经知道如何在 Awk 脚本中进行类似 c 的复合赋值。作为旁注,至于为什么我可能使用速记,我认为优点是显而易见的——它很短。但是就像正则表达式一样,你可能想写一个好的为了后代的缘故,描述您令人困惑的语法所做的事情。

【问题讨论】:

    标签: scripting awk conditional variable-assignment compound-assignment


    【解决方案1】:

    实际上,C 也有 ? 运算符,所以你可以用 C 做同样的(丑陋的)事情。

    但是,您实际上是在制作只写代码。如果你没有告诉我那个 awk 语句做了什么,那将很难弄清楚。为什么不直接使用if

    当你发现需要调整它时,你会在 6 个月内感谢自己。

    【讨论】:

    • 如果你理解语法,你可以把它分解成一系列的 if 语句,应该不难理解。另外,这就是你的单行文件中的 cmets 的用途:) 我喜欢它,因为它很短,但如果有这样的事情,我更喜欢适当的复合条件缩短......
    【解决方案2】:

    (a) 我想是的

    (b) 是


    碰巧的是,您的“C”代码几乎是合法的 awk。以下稍作调整的版本作为 awk 程序运行良好...

    /./ {
      price = $1
      if (price > 40.00) {
         price -= 2 
         price *= 1.06 
      } else if ( price > 20.00 && price <= 40.00 ) {
         price-- 
         price *= 1.06 
      } else if ( price > 1.00 ) {
         price *= 1.06
      }
      printf("%6.2f\n", price)
    }
    

    我把分号去掉了,但是如果你把它们留在里面也没什么不好的......

    【讨论】:

    • err... 我专门指的是赋值简写 (<...>)?<...>:<...> ...我已经知道如何使用传统条件句。我已经在我的帖子中添加了额外的说明,所以没有其他人像你一样感到困惑。
    • 好的,明白了,但是您确实说过“使用像 C 这样的语言”,而且您的“C”在 awk 中工作真是太酷了。显然,?:if-then-else 之间存在一般等价性。现在,很酷的前沿是像 Ruby 这样的东西,它可以让你说(x?y:z; whatever; if x ...; and_do_something_else),你可以把它放在任何地方,包括 ((((())))) 中的表达式中的任意语句......
    • 是的,我知道这有点令人困惑......对此感到抱歉。这听起来像是一个在 Ruby 中用于复合执行的有趣工具……
    【解决方案3】:

    a)

    Bash、ksh 和 zsh 支持复合条件(三元)运算符(不过,Bash 不做浮点数):

    for i in {3..5}; do for j in {2..6}; do for k in {2..4}; do
        (( a = i > j ? i > k ? j > k ? i * j : i * k : j * k : 0 ))
        echo $a
    done; done; done
    

    PHP 的三元运算符语法类似。

    Python 完全不同:

    a = b if c else d if e else f if g else h
    

    Bash 等人和 Ruby(也支持 ?: 形式)支持这种风格(显示 Bash 的版本):

    [[ condition ]] && do_if_true || do_if_false
    

    这可以以复合形式完成。这可以执行除分配之外的操作。

    b) 不,不是没有明确的if/else(或者诉诸更多kludginess创造力。

    【讨论】:

    • 哇很好的答案!先生,您是真正的脚本专家。只是我概述的那种信息......你有没有想过写一本脚本书? :P
    • @Jason:我的脑海里闪过这个念头,但书里已经没有钱了。
    • 那么可能是一个网站? :P 似乎有某种方式可以很好地利用教育人才。经常(免费)的帮助很感激!
    猜你喜欢
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多