【问题标题】:How to replace a word from a file with elements in an array如何用数组中的元素替换文件中的单词
【发布时间】:2019-11-06 09:42:39
【问题描述】:

我正在尝试将所有单词“null”替换为数组中的元素。问题是在替换了一个“null”之后,我想用数组中的下一个元素替换下一个“null”。

我不太擅长 bash,我觉得这是一个相当基本的问题。

这是我目前所拥有的:

for m in $(cat finalfile.csv)
do
    if [ "$m" = "null" ]
    then
        m=cwearray[$counter]
        let counter++
    fi
done

这不会替换 finalfile.csv 中的任何内容。

例如,如果文件有:

"value1","value2","null","value3"\n
"value1","value2","null","value3"...

并且数组有 ["foo","bar"]

我希望它是:

"value1","value2","foo","value3"\n
"value1","value2","bar","value3"...

【问题讨论】:

  • 您是否更改了字段分隔符?如果不是,则文件将在换行符上拆分。因此,您的 $m 将是整行。
  • 我试图让它在每次遇到“null”时都回显“它的 null”,并且回显的数量是正确的,所以我认为 for 循环正确地找到了“null”值,只是没有改变它到数组中的元素

标签: arrays string bash replace str-replace


【解决方案1】:

在 Perl 中更容易,您可以直接在替换的替换部分增加索引:

printf '%s\n' 1,2,3,null null,2,3,4 null,null,null,null \
| perl -pe 'BEGIN { @cwe = qw( A B C D E F ) }
            s/(?:^|(?<=,))null(?=,|$)/$cwe[$i++]/g'

更新:您似乎已使用示例输入更新了您的问题。如果空值是双引号,它会变得更容易,因为不需要检查它们是否用逗号 括在行的开头/结尾。

perl -pe 'BEGIN{ @cwe = qw( foo bar ) }
          s/"null"/"$cwe[$i++]"/g'

【讨论】:

  • 我有一个疑问..如果两个空值在同一行会发生什么?
  • @CorentinLimier:尝试运行第一个示例,它已经在同一行包含 4 个空值。
  • 那么我现在喜欢 perl
【解决方案2】:

逐行读取文件。如果一行包含null,则使用sed 将所有出现的null 替换为相应的值,通过数组索引检索。

#!/bin/bash

file="finalfile.csv"
counter=0

array=(
  "foo"
  "bar"
)

while read -r line; do
  item="${array[$counter]}"
  echo "$line" | sed "s/null/$item/g"
  ((counter++))
done < "$file"

【讨论】:

  • 如果同一行有两个null或者某行不包含null,则不起作用。
  • @corentin-limier - 确实如此。自己试试吧。
  • 我试过了。 array=("foo" "bar" "foobar") 和 finalfile.csv 像这样:"null","null"\n"a","b"\n"a","b"\n"null","c"\n
  • 它返回 "foo","foo"\n"a","b"\n""a","b"\n"","c"\n 这不是 OP 想要的
  • 应该是"foo","bar"\n"a","b"\n"a","b"\n"foobar","c"\n
【解决方案3】:

一个 awk 解决方案:

declare -a cwearray
cwearray=(foo bar)
awk -F, 'NR==FNR{repl[NR]=$0; next}{for(i=1;i<=NF;i++){if($i=="\"null\""){$i="\""repl[++counter]"\""}}}1' OFS="," <(for i in "${cwearray[@]}"; do echo "$i"; done) <file>

【讨论】:

    【解决方案4】:

    可以用 bash 完成,即使每行有多个空值:

    $ cat finalfile.csv
    "value1","value2","null","null"
    "value1","value2","null","value3"
    
    $ cwearray=( foo bar baz )
    
    $ idx=0
    
    $ while read -r line; do 
        while [[ $line == *null* ]]; do 
          line=${line/null/${cwearray[idx++]}}
          # ...............^^^^^^^^^^^^^^^^^^
          # replace the _first_ "null" with the _next_ array element
        done
        echo "$line"
      done < finalfile.csv > updatedfinalfile.csv
    
    $ cat updatedfinalfile.csv
    "value1","value2","foo","bar"
    "value1","value2","baz","value3"
    

    【讨论】:

    • 替换一行上的所有nulls(而不仅仅是第一个),可以改为:line=${line//null/${cwearray[idx++]}}
    • 这将用相同的替换更改行上的所有空值,所以不是OP想要的。
    猜你喜欢
    • 2021-12-07
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多