【问题标题】:set multiple variables from one awk command?从一个 awk 命令设置多个变量?
【发布时间】:2021-10-06 17:46:03
【问题描述】:

这是一个很常见的脚本:

#!/bin/bash

teststr="col1 col2"

var1=`echo ${teststr} | awk '{print $1}'`
var2=`echo ${teststr} | awk '{print $2}'`

echo var1=${var1}
echo var2=${var2}

但是我不喜欢这样,尤其是当有更多字段要解析时。 我想应该有更好的方法,比如:

(var1,var2)=`echo ${teststr} | awk '{打印 $1 $2}' (在我的想象中)

是这样吗? 感谢您帮助提高效率并节省一些 CPU 功率。

【问题讨论】:

  • read -r a b < <(awk '{print $1, $2}' <<< "hello world")

标签: bash awk


【解决方案1】:

这可能对你有用:

var=(col0 col1 col2)
echo "${var[1]}"
col1

【讨论】:

  • 感谢提醒我 bash arries。这就是解决方案。也可以这样写:var=(echo ${blabla} | awk -F"_" '{print $1 " " $3}')...
【解决方案2】:

Bash 支持数组,我们只需要动态提供值:)

function test_set_array_from_awk(){

    # Note : -a is required as declaring array
    let -a myArr;

    # Hard Coded Valeus 
    # myArr=( "Foo" "Bar" "other" );
    # echo "${myArr[1]}" # Print Bar 

    # Dynamic values 
    myArr=( $(echo "" | awk '{print "Foo"; print "Bar"; print "Fooo-And-Bar"; }') );

    # Value @index 0 
    echo "${myArr[0]}" # Print Foo

    # Value @index 1
    echo "${myArr[1]}" # Print Bar 

    # Array Length 
    echo ${#myArr[@]}  # Print 3 as array length 

    # Safe Reading with Default value 
    echo "${myArr[10]-"Some-Default-Value"}" # Print Some-Default-Value
    echo "${myArr[10]-0}"    # Print 0  
    echo "${myArr[10]-''}"   # Print ''
    echo "${myArr[10]-}"     # Print nothing

    # With Dynamic Index 
    local n=2
    echo "${myArr["${n}"]-}" # Print Fooo-And-Bar

}

# calling test function
test_set_array_from_awk

Bash 数组文档:http://tldp.org/LDP/abs/html/arrays.html

【讨论】:

    【解决方案3】:

    您还可以使用 shell set builtin 将空格分隔(或更准确地说,IFS 分隔)放入变量 $1、$2 等:

    #!/bin/bash
    
    teststr="col1 col2"
    set -- $teststr
    echo "$1" # col1
    echo "$2" # col2
    

    【讨论】:

      【解决方案4】:

      可以,但最佳做法是使用 awk 方式将变量传递给 awk。

      使用 shell 脚本变量的示例

      awk -v awkVar1="$scriptVar1" -v awkVar2="$scriptVar2" '<your awk code>'
      

      使用环境变量的示例

      awk -v awkVar1=ENVIRON["ENV_VAR1"] -v awkVar2=ENVIRON["ENV_VAR2"] '<your awk code>'
      

      可以同时使用脚本和环境变量

      awk -v awkVar1=ENVIRON["ENV_VAR1"] -v awkVar2="$scriptVar2" '<your awk code>'
      

      您可能会发现 bash 技巧来规避 awk 的做法,但这并不安全。

      说明和更多示例

      Awk 以这种方式工作,因为它本身就是一种编程语言,并且有自己的方式在 awk 语句中使用变量。

      “inside”是指单引号之间的部分。

      让我们看一个示例,我们在配置文件中关闭 DHCP,所有这些都使用 shell 脚本使用变量完成。我将解释最后一行代码。

      脚本不是最优的,它的主要目的是使用脚本变量。解释脚本是如何工作的超出了这个答案的范围,重点是解释变量的使用。

      #!/bin/bash
      
      # set some variables
      
      # set path to the config file to edit
      CONFIG_FILE=/etc/netplan/01-netcfg.yaml
      
      # find the line number of the line to change using awk and assign it to a variable
      DHCP_LINE=$(awk '/dhcp4: yes/{print FNR}' $CONFIG_FILE)
      
      # get the number of spaces used for identation using awk and assign it to a variable
      SPACES=$(awk -v awkDHCP_LINE="$DHCP_LINE" 'FNR==awkDHCP_LINE {print match($0,/[^ ]|$/)-1}' $CONFIG_FILE)
      
      # find DHCP setting and turn it off if needed
      awk -v awkDHCP_LINE="$DHCP_LINE" -v awkSPACES="$SPACES" 'FNR==awkDHCP_LINE {sub("dhcp4: yes", "dhcp4: no")}' $CONFIG_FILE
      

      让我们把最后一行分解成几段来解释。

      awk -v awkDHCP_LINE="$DHCP_LINE" -v awkSPACES="$SPACES"

      上面这部分将DHCP_LINE脚本变量的值赋给awkDHCP_LINEawk变量,将SPACES脚本变量的值赋给awkSPACESawk变量。

      请注意,SPACES 变量被传递给 awk 只是为了展示如何传递多个变量; awk 命令不处理它。

      'FNR==awkDHCP_LINE {sub("dhcp4: yes", "dhcp4: no")}'

      上面这个是 awk 的“inside”部分,可以使用传递给 awk 的变量。

      $CONFIG_FILE

      这部分是outside awk,一个通用的脚本变量用来指定要处理的文件。

      我希望这能澄清一些事情:)

      注意:如果您有很多变量要传递,@potong 提供的解决方案可能会证明是更好的方法,具体取决于您的用例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-12
        • 2014-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多