0

我有一个看起来像这样的文件:

abs=1 sin=2.1 cat=曲线=3
abs=2 sin=3.4 cat=锯齿线=8
abs=7 sin=6.3 cat=方线=4

实际上,我还有几个字段,并非所有行都有所有字段。无论如何,我想编写一个脚本,用户可以在其中定义他们想要保留的元组的“掩码”(例如 abs、line),然后脚本输出一个较小版本的文件,其中只有给定字段中的值。

例如,我给脚本一个输入参数“abs,line”,它会打印:

绝对=1 行=3
绝对=2 线=8
绝对=7 线=4

我在 bash 中做了几件这样的事情,并希望将其集成到我的 bash 脚本中。我在想 awk 必须能够做到这一点,但我不太清楚如何做到这一点。

4

3 回答 3

2

更新以填充glenn在评论中建议的掩码,这使得匹配更加健壮:

mask=abs,line
awk -v mask=$mask -v RS='[\n ]' -v FS='=' -v ORS='' '
  BEGIN { mask="," mask "," }
  mask ~ "," $1 "," { print $1 FS $2 RT }
'

请注意,将mask变量设置为要提取的参数的逗号分隔列表。

记录由换行符或空格分隔,并在末尾重新插入RT

输出:

abs=1 line=3
abs=2 line=8
abs=7 line=4
于 2012-08-27T16:34:04.110 回答
1

我会制作absline分隔参数,而不是一个逗号分隔的参数,使脚本如下所示:

#!/bin/bash
declare -A keep;

# read variables to keep from command line into associative array
while (( $# )); do
  keep[$1]=1
  shift
done

# process input
while read -r; do
  read -a args <<<"$REPLY"
  for arg in "${args[@]}"; do
    key=${arg%=*}
    value=${arg#*=}
    if [[ ${keep[$key]} ]] ; then
      printf '%s=%s ' "$key" "$value"
    fi
  done
  printf '\n'
done

然后运行脚本如下:

./yourscript abs line <input.txt
于 2012-08-27T15:55:16.173 回答
0

其他方法使用awk

假设infile粘贴在问题中的内容,创建掩码并执行以下脚本:

m="abs,line,cat"; awk -v mask="$m" '
    BEGIN {
        OFS = " ";

        ## Set fields of the mask as keys of an array.
        ret = split( mask, arr, /,/ );
        for ( i = 1; i <= length( arr ); i++ ) {
            mask_arr[ arr[i] ] = 1;
        }
    }

    ## Go throught all fields, extract the first part until the equal sign,
    ## search it in the array and print if found.
    {
        for ( i = 1; i <= NF; i++ ) {
            if ( substr( $i, 1, index( $i, "=" ) - 1 ) in mask_arr ) {
                printf "%s%s", $i, OFS;
            }
        }
        printf "\n";
    }
' infile

结果是:

abs=1 cat=curve line=3 
abs=2 cat=sawtooth line=8 
abs=7 cat=square line=4
于 2012-08-27T18:41:26.570 回答