【问题标题】:Split string with | character in Bash and export environment variables from first row用 | 分割字符串Bash 中的字符并从第一行导出环境变量
【发布时间】:2019-05-11 10:34:58
【问题描述】:

我有以下从网络服务获得的字符串:

user@server:~# cat test.txt
account|uname|upass|mac|ip|tariff|download|upload
11122|24a43cda22b2|O3v2L2oPE9|24:A4:3C:DA:22:B2|192.168.1.2|7|12582500|2097000

第一行是列名,第二行是它们各自的值。请注意,响应总是返回这两行,而不是更多。我不能使用 JSON 或其他结构化响应格式,这是我必须使用的。

我的目标是通过分隔符 | 拆分所有这些值,并使用列名作为变量名来设置环境变量(或我的 .sh 脚本上下文中的变量)。

到目前为止,我可以使用以下命令将两行与| 分开:

user@server:~# head -n1 test.txt | sed 's/|/\n/g'
account
uname
upass
mac
ip
tariff
download
upload

user@server:~# head -n2 test.txt | sed 's/|/\n/g'
11122
24a43cda22b2
O3v2L2oPE9
24:A4:3C:DA:22:B2
192.168.1.2
7
12582500
2097000

从这里我想定义变量,即。 $account, $uname 等具有以下值:

$account = 11122
$uname = 24a43cda22b2

将它们作为系统环境变量(直到重新启动或下次执行我的 .sh 脚本)或在 shell 脚本本身的上下文中。

【问题讨论】:

    标签: bash sed environment-variables


    【解决方案1】:

    按要求取 3:awk

    $: awk -F'|'  'BEGIN{ ORS="" }
      NR == 1  { for ( i=0; i <= NF; i++ ) { arr[i] = $i;                  }; }
      NR == 2  { for ( i=1; i <= NF; i++ ) { printf "%s=%s\n", arr[i], $i; }; }
    ' test.txt > /tmp/vars
    $: . /tmp/vars
    

    Take 2:为sh重写

    希望这会有所帮助。 :)

    $: cat parse
    #! /bin/env sh
    
    sed -n '
      s/[|]/\n/g
      1 w /tmp/names
      2 w /tmp/vals
    ' $1
    
    paste /tmp/names /tmp/vals | sed 's/\t/=/' >/tmp/vars
    
    $: cat /tmp/vars
    account=11122
    uname=24a43cda22b2
    upass=O3v2L2oPE9
    mac=24:A4:3C:DA:22:B2
    ip=192.168.1.2
    tariff=7
    download=12582500
    upload=2097000
    
    $: . /tmp/vars
    $: echo $account
    11122
    

    原文供参考

    printf -v 将为您写入指定的变量名。

    $: cat parse
    #! /bin/env bash
    
    { IFS='|' read -a headers
      IFS='|' read -a data
    } < $1
    
    declare -i ndx=0
    for h in "${headers[@]}"
    do  printf -v "$h" "%s" "${data[ndx++]}"
    done
    
    echo "account=$account uname=$uname upass=$upass mac=$mac ip=$ip tariff=$tariff download=$download upload=$upload"
    

    执行为:

    $: parse test.txt >vars
    

    输出:

    $: cat vars
    account=11122 uname=24a43cda22b2 upass=O3v2L2oPE9 mac=24:A4:3C:DA:22:B2 ip=192.168.1.2 tariff=7 download=12582500 upload=2097000
    

    将这些值加载到作用域中:

    $: parse test.txt >vars
    $: . vars
    

    即使在 sh 中,采购输出也应该满足您的需求。

    【讨论】:

    • 这比公认的答案更合适。我建议避免使用seq,而只是遍历数组。类似i=0; for k in "${headers[@]}"; do echo printf -v "$k" "${data[$((++i))]}"; done
    • 啊。好的,那么,看看我是否可以生成一个功能替代品。给我一点。
    • 乐于助人。 ;)
    • 如果我们使用awk 更容易只使用awk 将输出文件写入源代码,哈哈
    • 我只是坚持不懈。 >;o]
    【解决方案2】:

    使用粘贴和 GNU sed:

    . <(paste -d= <(sed -n '1s/|/\n/gp' test.txt) <(sed -n '2s/|/\n/gp' test.txt))
    

    或者如果 GNU datamash 可用:

    . <(datamash -t '|' --output-delimiter='=' transpose < test.txt)
    

    然后:

    echo $account $mac $ip
    

    将输出:

    11122 24:A4:3C:DA:22:B2 192.168.1.2
    

    【讨论】:

    • paste 不可用。我在sh 下运行它,bash 也不可用。我有以下工作:readawksedheadcatgrep 和其他基本程序。我在busybox/mips GNU linux上运行它。
    【解决方案3】:

    如果标题是固定的,read 就足够了:

    IFS='|' read account uname upass mac ip tariff download upload < <(tail -n1 test.txt)
    echo $account $ip
    

    输出:

    11122 192.168.1.2
    

    【讨论】:

      【解决方案4】:

      这就是你想要的:

      awk -F'|'  'BEGIN{ ORS="" } { for ( i=1; i<= NF && NR == 1; i++){ arr[i]=$i  } ; if (NR == 1)  next ; for ( i=1; i<= NF ; i++ ) { print arr[i]"="'\''$i'\''"\n" } } ' input.txt
      
      
      account=11122
      uname=24a43cda22b2
      upass=O3v2L2oPE9
      mac=24:A4:3C:DA:22:B2
      ip=192.168.1.2
      tariff=7
      download=12582500
      upload=2097000
      

      编辑:声明时不需要美元符号。 编辑:为了实际将其设置为环境变量,您可以将其输出重定向到文件 /etc/environment ,如下所示:

      awk -F'|'  'BEGIN{ ORS="" } { for ( i=1; i<= NF && NR == 1; i++){ arr[i]=$i  } ; if (NR == 1)  next ; for ( i=1; i<= NF ; i++ ) { print arr[i]"="'\''$i'\''"\n" } } ' input.txt >> /etc/environment
      

      你当然需要 sudo

      希望对你有帮助!

      【讨论】:

      • 没有。它不导出变量。再次阅读我的问题。
      • 我已经编辑了我的答案。为了将这些值设置为环境变量,您需要在某处定义它们。 /etc/environment 是个好地方。为此,只需重定向输出。请记住,您需要拥有 sudo 访问权限才能修改我提到的那个文件,此外,您还需要注销并重新登录才能看到所反映的更改。
      猜你喜欢
      • 2017-09-15
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 2015-01-29
      • 1970-01-01
      • 2012-05-25
      • 2021-12-17
      相关资源
      最近更新 更多