【问题标题】:Setting multiple field to awk variables at once一次将多个字段设置为 awk 变量
【发布时间】:2012-10-05 04:31:52
【问题描述】:

我正在尝试一次将一个 awk 变量字段设置为多个字段。

现在只能一一设置变量。

for line in `cat file.txt`;do
    var1=`echo $line | awk -F, '{print $1}'`
    var2=`echo $line | awk -F, '{print $2}'`
    var3=`echo $line | awk -F, '{print $3}'`

    #Some complex code....
done

我认为这是昂贵的,因为它会多次解析 linux 变量。是否有一种特殊的语法可以一次设置变量?我知道 awk 有一个 BEGIN 和 END 块,但我试图避免 BEGIN 和 END 块的原因是为了避免嵌套的 awk。

我打算在 #Some complex code.... 部分中放置另一个循环和 awk 代码。

for line in `cat file.txt`;do
    var1=`echo $line | awk -F, '{print $1}'`
    var2=`echo $line | awk -F, '{print $2}'`
    var3=`echo $line | awk -F, '{print $3}'`

    for line2 in `cat file_old.txt`;do
        vara=`echo $line2 | awk -F, '{print $1}'`
        varb=`echo $line2 | awk -F, '{print $2}'`

        # Do comparison of $var1,var2 and $vara,$varb , then do something with either
    done
done

【问题讨论】:

  • 为什么不使用awk 进行比较和“做某事”?
  • 你能给出一个使用两个文件与 awk 相比的示例代码吗?请注意,两个文件 file.txt 和 file_old.txt 可以有不同的行大小。
  • 抱歉,我错过了您想将它们相互比较的信息。取决于您要解决的具体问题和文件的结构,但我的强烈印象是我们有更好的解决方案。
  • 是的,这听起来绝对像XY problem

标签: bash awk


【解决方案1】:

您可以使用IFS 内部字段分隔符来使用逗号(而不是空格)并在while 循环中进行分配:

SAVEIFS=$IFS;
IFS=',';
while read line; do
    set -- $line;
    var1=$1;
    var2=$2;
    var3=$3;
    ...
done < file.txt

IFS=$SAVEIFS;

这将保存您当前IFS 的副本,将其更改为, 字符,然后遍历文件中的每一行。 set -- $line; 行会将每个单词(用逗号分隔)转换为数字变量($1$2 等)。您可以直接使用这些变量,也可以将它们分配给其他(更有意义的)变量名。

或者,您可以将IFS 与威廉提供的答案一起使用:

IFS=',';
while read var1 var2 var3; do
    ...
done < file.txt

它们在功能上是相同的,只是取决于您是否要显式设置var1=$1 或在while-loop 的头部中定义它。

【讨论】:

  • 嵌套两个while循环有问题吗?变量 $1 $2 $3 会有影响吗?
  • 如果您在嵌套循环中再次调用set -- $variable;,则设置的$1$2、..、$n 变量也将在父循环中被覆盖。因此,如果您想使用该方法,您可能需要确保先将它们分配给其他变量。
【解决方案2】:

你为什么要使用awk

while IFS=, read var1 var2 var3; do
  ...
done < file.txt

【讨论】:

  • 如果数据是逗号分隔的,同样的方法也适用于将输入字段分隔符设置为“,”。在while循环之前添加IFS=','
【解决方案3】:
#!/bin/bash    
FILE="/tmp/values.txt"

    function parse_csv() { 
    local lines=$lines;
    > $FILE
    OLDIFS=$IFS;
    IFS=","
    i=0
    for val in ${lines}
    do
      i=$((++i))
      eval var${i}="${val}"
    done
    IFS=$OLDIFS;
    for ((j=1;j<=i;++j))
    do
      name="var${j}"
      echo ${!name} >> $FILE
    done

    }

    for lines in `cat file_old.txt`;do
     parse_csv;
    done

您描述的问题只有 3 个值,是否有可能 3 个值可能不同并且是 4 或 5 或未定义?

如果是这样,上面将逐行解析 csv 并在名为 /tmp/values.txt 的文件中的新行上一次输出每个值

随意修改以满足您的要求,它比定义 3 个值更具动态性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    相关资源
    最近更新 更多