在bash中从字符串中获取值

时间:2014-06-12 12:26:29

标签: string bash

我希望你能帮助我。 我尝试分离一个字符串:

#!/bin/bash


file=$(<sample.txt)
echo "$file"

文件本身包含如下值:

(;FF[4]GM[1]SZ[19]CA[UTF-8]SO[sometext]BC[cn]WC[ja]

我需要的是一种在[]之间提取值并将它们设置为变量的方法,例如:

$FF=4
$GM=1
$SZ=19
and so on

但是,某些文件不包含所有值,因此在某些情况下没有FF [*]。在这种情况下,程序应使用值“99”

我该怎么做?

非常感谢你的帮助。 问候 克里斯

4 个答案:

答案 0 :(得分:1)

这可能有点过于复杂,但这是另一种方式:

grep -Po '[-a-zA-Z0-9]*' file | awk '!(NR%2) {printf "declare %s=\"%s\";\n", a,$0; next} {a=$0} | bash

按步骤

通过仅打印所需的块来过滤文件:

$ grep -Po '[-a-zA-Z0-9]*' a
FF
4
GM
1
SZ
19
CA
UTF-8
SO
sometext
BC
cn
WC
ja

重新格式化,以便指定声明:

$ grep -Po '[-a-zA-Z0-9]*' a | awk '!(NR%2) {printf "declare %s=\"%s\";\n", a,$0; next} {a=$0}' 
declare FF="4";
declare GM="1";
declare SZ="19";
declare CA="UTF-8";
declare SO="sometext";
declare BC="cn";
declare WC="ja";

最后管道进行bash以便它被执行。

注意第二步也可以改写为

xargs -n2 | awk '{print "declare"$1"=\""$2"\";"}'

答案 1 :(得分:1)

我使用;[]作为awk的字段分隔符来写这个

$ line='(;FF[4]GM[1]SZ[19]CA[UTF-8]SO[sometext]BC[cn]WC[ja]'
$ awk -F '[][;]' '{for (i=2; i<NF; i+=2) {printf "%s=\"%s\" ", $i, $(i+1)}; print ""}' <<<"$line"
FF="4" GM="1" SZ="19" CA="UTF-8" SO="sometext" BC="cn" WC="ja" 

然后,评估当前shell中的输出:

$ source <(!!)
source <(awk -F '[][;]' '{for (i=2; i<NF; i+=2) {printf "%s=\"%s\" ", $i, $(i+1)}; print ""}' <<<"$line")
$ echo $SO
sometext

要处理默认的FF值:

$ source <(awk -F '[][;]' '{
   print "FF=99"
   for (i=2; i<NF; i+=2) printf "%s=\"%s\" ", $i, $(i+1)
   print ""
}' <<< "(;A[1]B[2]")
$ echo $FF
99
$ source <(awk -F '[][;]' '{
   print "FF=99"
   for (i=2; i<NF; i+=2) printf "%s=\"%s\" ", $i, $(i+1)
   print ""
}' <<< "(;A[1]B[2]FF[3]")
$ echo $FF
3

答案 2 :(得分:0)

根据您的要求:

while IFS=\[ read -r A B; do
    [[ -z $B ]] && B=99
    eval "$A=\$B"
done < <(exec grep -oE '[[:alpha:]]+\[[^]]*' sample.txt)

尽管使用关联数组会更好:

declare -A VALUES

while IFS=\[ read -r A B; do
    [[ -z $B ]] && B=99
    VALUES[$A]=$B
done < <(exec grep -oE '[[:alpha:]]+\[[^]]*' sample.txt)

您可以同时访问密钥("${!VALUES[@]}")和值"${VALUES['FF']}"

答案 3 :(得分:0)

我可能会这样做:

set $(sed -e 's/^(;//' sample.txt | tr '[][]' ' ')
while (( $# > 2 ))
do
  varname=${1}
  varvalue=${2}

  # do something to test varname and varvalue to make sure they're sane/safe

  declare "${varname}=${varvalue}"

  shift 2
done