Bash for循环数组

时间:2017-03-28 08:21:42

标签: bash for-loop

我正在写一个小bash脚本来工作。但现在我被卡住了。让我告诉你代码并解释一下:

# I have an `array` with names
NAMES=(Skypper Lampart Shepard Ryan Dean Jensen)

现在我想通过名字

进行迭代
for (( i = 0; i < 6; i++ )); do
    COMMAND="sed -i ${i+2}s/.*/${NAMES[${i}]}"
    ${COMMAND} config.txt
done

config.txt是一个包含2个数字和名字的文件,我只想替换名称。

1
2
Name 1
Name 2
Name 3
Name 4
Name 5
Name 6

我的问题出在for - 循环中如何制作$i + 2?因此,如果我$i为1则应为3。

预期产出:

1
2
Skypper
Lampart
Shepard
Ryan
Dean
Jensen

5 个答案:

答案 0 :(得分:1)

Bash擅长阅读数组(你可以轻松搜索的内容)。

尝试类似:

for idx in "${!NAMES[@]}"
do
  sed -i "$((idx + 2))s/.*/${NAMES[idx]} $idx/" config.txt
done

除非你知道自己在做什么,否则你会发现在变量中放置命令也会失效,所以只需按预期使用命令:)

您可能还需要记住索引从零开始而不是1

答案 1 :(得分:1)

如果我理解你想要完成什么(用NAMES数组中的字符串替换“Name”,数组中索引的问题从0开始,你想从第3行开始) - 脏和快速的解决方案是添加2将字符串清空到数组的开头,然后从你想要的位置开始循环。

答案 2 :(得分:1)

使用此:

NAMES=(Skypper Lampart Shepard Ryan Dean Jensen)
line=2  # Need to skip first 2 lines
for name in "${NAMES[@]}"
do
    ((line++))
    sed -i "${line}s/.*/$name/g" config.txt
done

答案 3 :(得分:1)

你可以尝试这样的事情:

NAMES=(Skypper Lampart Shepard Ryan Dean Jensen)
for (( i = 0; i < 6; i++ )); do
    b=$(( $i+2 ))
    COMMAND="sed -i $b s/.*/${NAMES[${i}]}"
    echo $COMMAND
#    ${COMMAND} config.txt
done

这给了我类似以下输出的内容:

# sh test.sh 
sed -i 2 s/.*/Skypper
sed -i 3 s/.*/Lampart
sed -i 4 s/.*/Shepard
sed -i 5 s/.*/Ryan
sed -i 6 s/.*/Dean
sed -i 7 s/.*/Jensen

答案 4 :(得分:1)

有点迟到的答案......:)

在您的代码中,您呼叫sed n次。这是低效的。因此,我提出了不同的解决方案,使用ed代替sed。 (正如30年前在BSD 2.9中的美好时光:) :)。

为此,方法:

  1. 首先为ed
  2. 创建命令
  3. 在一个编辑器调用中执行它们
  4. # it is good practice not using UPPERCASE variables
    # as theycould collide with ENV variables
    
    names=(Skypper Lampart Shepard Ryan Dean Jensen)
    file="config.txt"
    
    #create an array of commands for the "ed"
    declare -a cmd
    for name in "${names[@]}"; do
        cmd+=("/Name/s//$name/")
    done
    cmd+=(w q)
    
    echo "=== [$file before] ==="
    cat "$file"
    
    echo "=== [commands for execution ]==="
    printf "%s\n" "${cmd[@]}"
    
    #execute the prepared command in the "ed"
    printf "%s\n" "${cmd[@]}" | ed -s "$file"
    
    echo "===[ $file after ]==="
    cat "$file"
    

    从上面输出

    === [config.txt before] ===
    1
    2
    Name 1
    Name 2
    Name 3
    Name 4
    Name 5
    Name 6
    === [commands for execution ]===
    /Name/s//Skypper/
    /Name/s//Lampart/
    /Name/s//Shepard/
    /Name/s//Ryan/
    /Name/s//Dean/
    /Name/s//Jensen/
    w
    q
    ===[ config.txt after ]===
    1
    2
    Skypper 1
    Lampart 2
    Shepard 3
    Ryan 4
    Dean 5
    Jensen 6
    

    替换为行号

    的变体
    names=(Skypper Lampart Shepard Ryan Dean Jensen)
    file="config.txt"
    
    #create an array of commands for the "ed"
    declare -a cmd
    n=3
    for name in "${names[@]}"; do
        cmd+=("${n}s/.*/$name/")
        let n++
    done
    cmd+=(w q)
    
    echo "=== [$file before] ==="
    cat "$file"
    
    echo "=== [commands for execution ]==="
    printf "%s\n" "${cmd[@]}"
    
    #execute the prepared command in the "ed"
    printf "%s\n" "${cmd[@]}" | ed -s "$file"
    
    echo "===[ $file after ]==="
    cat "$file"
    

    输出

    === [config.txt before] ===
    1
    2
    Name 1
    Name 2
    Name 3
    Name 4
    Name 5
    Name 6
    === [commands for execution ]===
    3s/.*/Skypper/
    4s/.*/Lampart/
    5s/.*/Shepard/
    6s/.*/Ryan/
    7s/.*/Dean/
    8s/.*/Jensen/
    w
    q
    ===[ config.txt after ]===
    1
    2
    Skypper
    Lampart
    Shepard
    Ryan
    Dean
    Jensen