bash - 当另一个变量中已知关联的子字符串时,确定一个变量中的子字符串

时间:2011-09-29 16:06:13

标签: bash sed awk

假设我有两个字符串,一个用作空格分隔键的字符串,另一个用作第一个键中每个键的关联空格分隔值:

KEYS="key_1 key_2 key_3"
VALS="value1 aDifferentValue_2 theFinalValue"

因此,在这种情况下,key_1中的$KEYS的关联值为value1key_2的关联值为aDifferentValue_2,依此类推。假设有问题的密钥是key_2,存储在变量$FIELD中,使用sed和/或awk最简单的方法是根据其单词位置查找该值,该值必须为{{1} }?有没有办法使用aDifferentValue_2的子串作为键并使用$KEYS作为值来创建关联数组?

6 个答案:

答案 0 :(得分:2)

由于这是标记为bash,因此您可以拥有实际的关联数组(bash v4):

KEYS="key_1 key_2 key_3"
VALS="value1 aDifferentValue_2 theFinalValue"
keys=( $KEYS )
vals=( $VALS )
declare -A map
for (( i=0; i<${#keys[@]}; i++ )); do
  map["${keys[$i]}"]="${vals[$i]}"
done
for idx in "${!map[@]}"; do
  echo "$idx -> ${map[$idx]}"
done

输出

key_1 -> value1
key_2 -> aDifferentValue_2
key_3 -> theFinalValue

如果您没有bash v4,仍然可以使用keysvals索引数组,并且:

get_key_idx() {
  for (( i=0; i<${#keys[@]}; i++ )); do 
    if [[ "$key" = "${keys[$i]}" ]]; then
      echo $i
      return 0
    fi
  done
  return 1
}

key="key_2"
if idx=$(get_key_idx $key); then
  echo "$key -> ${vals[$idx]}"
else
  echo "no mapping for $key"
fi

答案 1 :(得分:1)

怎么样:

变量:

/home/sirch>KEYS="key_1 key_2 key_3"
/home/sirch>VALS="value1 aDifferentValue_2 theFinalValue"

代码:

/home/sirch>cat s.awk
BEGIN{
    split(keystring,key," ");
    split(valstring,temp," ")
    for(i=1;i<=length(key);i++)val[key[i]]=temp[i]
}
END{print val["key_2"]}

输出:

/home/sirch>awk -v "keystring=$KEYS" -v "valstring=$VALS" -v "query=key_02" -f s.awk f
aDifferentValue_2

首先设置shell变量KEYS和VALS。然后将它们作为字符串导出到akw。 然后将这些字符串拆分为空格,将结果数组保存在“key”和“temp”中。 temp ist用于创建vinal hashmap“val”。现在,您可以查询val [“key_1”]等,以从VALS-shell字符串中获取相应的值。

要从shell脚本运行此命令,只需将awk脚本保存到文件即可。然后将shell变量查询设置为查询字符串,并使用此变量从shell脚本中调用awk-script。你将给出一个虚拟文件,这里是“f”,作为awk的参数,使这个工作。

HTH Chris

答案 2 :(得分:1)

Pure POSIX shell:

#!/bin/sh

# set -x

assoc() {
  keys="$1 "
  values="$2 "
  key=$3
  while [ -n "$keys" -a -n "$values" ]; do
    key_=${keys%% *}
    keys=${keys#* }
    value_=${values%% *}
    values=${values#* }
    if [ $key_ = $key ]; then
      echo $value_
      return 0
    fi
  done
  return 1
}

keys='a b c'
values='1 2 3'
key=b
echo Value for key $key is _`assoc "$keys" "$values" "$key"`_

keys='a b c'
values='1 2 3'
key=xxx
echo Value for key $key is _`assoc "$keys" "$values" "$key"`_

keys='a b c'
values='1 2 3 4 5'
key=c
echo Value for key $key is _`assoc "$keys" "$values" "$key"`_

keys='a b c'
values='1 2'
key=c
echo Value for key $key is _`assoc "$keys" "$values" "$key"`_

运行时:

  bash# ./1.sh   
Value for key b is _2_
Value for key xxx is __
Value for key c is _3_
Value for key c is __

答案 3 :(得分:0)

这是一个仅限bash的选择:

#!/bin/bash -x

KEYS="key_1 key_2 key_3"
VALS="value1 aDifferentValue_2 theFinalValue"

assoc() {
    read fkey rkeys
    read fval rvals
    if [ "X$fkey" == "X$1" ] ; then echo $fval; exit 0; fi
    if [ "X$rkeys" == "X" ] ; then exit 1; fi
    echo -e "$rkeys\n$rvals" | assoc $1
}

echo -e "$KEYS\n$VALS" | assoc key_2

答案 4 :(得分:0)

另一个AWK解决方案(可能更短?)

echo "$keys $vals"|awk '{t=NF/2;for(i=1;i<=t;i++)a[$i]=$(i+t);}{print a[KeyYouWANT]}'

<强>试验:

kent$  keys="key_1 key_2 key_3"    
kent$  vals="value1 aDifferentValue_2 theFinalValue"
kent$  echo "$keys $vals"|awk '{t=NF/2;for(i=1;i<=t;i++)a[$i]=$(i+t);} END{print a["key_2"]}'  

aDifferentValue_2

您也可以将所需的keyStr放在变量

kent$  want=key_3
kent$  echo "$keys $vals"|awk -v x=$want '{t=NF/2;for(i=1;i<=t;i++)a[$i]=$(i+t);} END{print a[x]}'   

theFinalValue

或者您想要查看完整列表:

kent$  echo "$keys $vals"|awk '{t=NF/2;for(i=1;i<=t;i++)a[$i]=$(i+t);} END{for(x in a)print x,a[x]}'

key_1 value1
key_2 aDifferentValue_2
key_3 theFinalValue

答案 5 :(得分:0)

这是一个sed解决方案:

keys="key_1 key_2 key_3" values="value_1 value_2 value_3" key="key_2" # variables used

str="$keys @@$values $key " # keys/values delimit by '@@' add key N.B. space after key!

sed -rn ':a;s/^(\S* )(.*@@)(\S* )(.*)/\2\4\1\3/;ta;s/^@@(\S* ).*\1(\S*).*/\2/p' <<<"$str"

# re-arrange keys/values into a lookup table then match on key using back reference