【问题标题】:bash How to declare and iterate over pairs of values where values may contain spaces (two dimensional array) [duplicate]bash如何声明和迭代可能包含空格的值对(二维数组)[重复]
【发布时间】:2015-12-28 13:19:27
【问题描述】:

1) 声明

例如,我有成对的目录。这些对包含空格(和/或其他不便之处,例如额外的句点或特殊字符。ext4 可以轻松支持的任何内容。)

'/foo/dolor sit/amet.elit'         '/bar/accumsan/luctus massa.nec'
'/baz/sagittis. Fusce/vitae.dolor' '/bam/Nunc aliquetjusto.metus'

我想编写一个 bash 脚本,其中这些对是硬编码/常量。

我非常希望在分隔符中声明字符串或不需要预处理任意字符串的字符串(例如,如果可能,我不想在所有文字空格上添加转义)


2) 迭代

使用声明的字符串对,我希望进入一个循环,其中两个字符串都可以在一次迭代中作为单独的变量使用,例如$LEFT$RIGHT

可能使用简单的文件操作,如复制、移动、链接、差异。


注意事项:

  • 数组的“高度”应允许多对。
  • 如果声明和迭代可以支持大于 2 的二维数组,请注意如何扩展为所需的。
  • 如果 bash 具有特定于“数组”的数据类型,则问题/答案不强制使用它。任何可迭代的二维声明和迭代就足够了。

【问题讨论】:

    标签: bash loops variables


    【解决方案1】:

    一种愚蠢而简单的方法,如果您仍要对数据进行硬编码,则可以将数据硬编码为 shell 函数的参数。

    #!/usr/bin/env bash
    
    do_for_pair() {
        echo "$1"
        echo "$2"
    }
    
    do_for_pair "/foo/dolor sit/amet.elit"         "/bar/accumsan/luctus massa.nec"
    do_for_pair "/baz/sagittis. Fusce/vitae.dolor" "/bam/Nunc aliquetjusto.metus"
    

    【讨论】:

    • 我喜欢这种方法。太务实了。
    • 函数中缺少的引用完全破坏了它。
    【解决方案2】:

    我会将配对列表放在此处的文档中,如下所示:

    : <<-'_pair_values_list_'
    '/foo/dolor sit/amet.elit' '/bar/accumsan/luctus massa.nec'
    '/baz/sagittis. Fusce/vitae.dolor' '/bam/Nunc aliquetjusto.metus'
    _pair_values_list_
    

    然后,假设单引号 ' 不是要成对使用的值的一部分,请阅读它们:

    #!/bin/bash
    i=0
    while IFS=\' read t LEFT t RIGHT t; do
        printf 'line count is: %4d ' "$(( ++i ))"
        printf 'with LEFT=%-35s' "$LEFT"
        printf 'with RIGHT=%-35s\n' "$RIGHT"
        done <<-'_pair_values_list_'
    '/foo/dolor sit/amet.elit' '/bar/accumsan/luctus massa.nec'
    '/baz/sagittis. Fusce/vitae.dolor' '/bam/Nunc aliquetjusto.metus'
    _pair_values_list_
    

    t 只是一个一次性变量。

    输出将是:

    line count is:    1 with LEFT=/foo/dolor sit/amet.elit           with RIGHT=/bar/accumsan/luctus massa.nec
    line count is:    2 with LEFT=/baz/sagittis. Fusce/vitae.dolor   with RIGHT=/bam/Nunc aliquetjusto.metus 
    

    如果对数增加太多(超过数百个),此处的文档 &lt;&lt;.... 可以稍后更改为文件 &lt;file.pairs

    如果将来需要更复杂的处理,可以将读取的变量(左右)分配给某个数组。我假设现在不需要。

    请注意,此脚本将能够处理包含换行符的文件名。

    【讨论】:

      【解决方案3】:

      在 Bash 中执行此操作的一种方法是将一对一个接一个地放在一个正常的线性数组中,然后一次遍历 2 个条目:

      filepairs=(
          '/foo/dolor sit/amet.elit'         '/bar/accumsan/luctus massa.nec'
          '/baz/sagittis. Fusce/vitae.dolor' '/bam/Nunc aliquetjusto.metus'
      )
      
      for (( idx=0 ; idx<${#filepairs[@]} ; idx+=2 )) ; do
          LEFT=${filepairs[idx]}
          RIGHT=${filepairs[idx+1]}
      
          echo "LEFT=$LEFT"
          echo "RIGHT=$RIGHT"
          echo
      done
      

      同样的技术可以用来处理更宽的二维数组。例如,要处理三元组,只需将它们一个接一个地放入数组中,一次遍历数组 3。

      【讨论】:

      • 这是我真正可以想象在 bash 中解决此问题的唯一方法,我犹豫是否使用它,因为我担心用户输入错误的可能性比任何其他解决方案都大。
      【解决方案4】:

      您可以使用关联数组(bash 4 或更高版本):

      declare -A arr
      arr['/foo/dolor sit/amet.elit']='/bar/accumsan/luctus massa.nec'
      arr['/baz/sagittis. Fusce/vitae.dolor']='/bam/Nunc aliquetjusto.metus'
      
      for LEFT in "${!arr[@]}"; do
          RIGHT=${arr["$LEFT"]}
          ...
      done
      

      【讨论】:

      • 没有理由犹豫将杂乱的值放在数组键字段中吗? bash 也不会按键名重新排序数组元素吗?
      • 它们的键可以是您可以正确引用的任何字符串。键的顺序是——不幸的是,如果这很重要的话——是任意的。
      • 在我的情况下,任意排序是可取的,如果我愿意,我可以自己按字母顺序排列它们。一定要问;我不知道对 bash 中的数组有什么期望,我希望它们会像所有 bash 登录和逻辑文档一样非常麻烦。
      【解决方案5】:

      我建议使用带有FPAT 的 gnu-awk 来拆分此文件,如下所示:

      awk -v FPAT="'[^']+'" '{system("echo cp \"" $1 "\" \"" $2 "\"")}' file
      

      输出:

      cp '/foo/dolor sit/amet.elit' '/bar/accumsan/luctus massa.nec'
      cp '/baz/sagittis. Fusce/vitae.dolor' '/bam/Nunc aliquetjusto.metus'
      

      验证输出后,您可以从 system 函数调用中删除 echo

      【讨论】:

      • 我不清楚如何在您的示例中使用 feild 1 和 feild 2 执行多个 shell 操作(抱歉,我没有澄清我想要的)。这个问题的目标之一(我再次没有澄清)是使用 LEFT 和 RIGHT 组件(作为路径)进行复制/移动/链接/差异操作。
      • 我建议用您想要对LEFTRIGHT 部分执行的操作来编辑问题,这样我也可以改进我的答案。
      • 我以为您建议进行一些编辑,现在我理解并编辑了迭代部分的文本,要求在一次迭代中同时提供 LEFT 和 RIGHT。
      猜你喜欢
      • 2016-11-05
      • 2013-05-05
      • 2013-01-13
      • 1970-01-01
      • 2014-04-01
      • 2014-04-30
      • 2014-01-03
      • 2016-07-07
      • 1970-01-01
      相关资源
      最近更新 更多