【问题标题】:Bash add increased number to string in a fileBash将增加的数字添加到文件中的字符串
【发布时间】:2022-01-11 23:19:16
【问题描述】:

我有这个属性文件,里面可以有尽可能多的“spark-worker”字符串:

[master]
spark-master ansible_ssh_host=ec2-3-236-23-XXX.compute-1.amazonaws.com

[worker]
spark-worker ansible_ssh_host=ec2-34-204-206-XXX.compute-1.amazonaws.com
spark-worker ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
.
.
spark-worker ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com

[spark_cluster:children]
master
worker

我想在每个字符串“spark-worker”之后添加一个数字,所以结果是:

[master]
spark-master ansible_ssh_host=ec2-3-236-23-XXX.compute-1.amazonaws.com

[worker]
spark-worker-1 ansible_ssh_host=ec2-34-204-206-XXX.compute-1.amazonaws.com
spark-worker-2 ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
.
.
spark-worker-n ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com

[spark_cluster:children]
master
worker

什么是最好的 bash 方式?

【问题讨论】:

  • 使用awk 是微不足道的。
  • 我认为sed 不可能,它没有任何算术能力,每次替换后都需要增加数字。

标签: bash shell awk sed


【解决方案1】:

一个awk单线:

awk '$1 == "spark-worker" { $1 = $1 "-" ++c } 1' file

【讨论】:

    【解决方案2】:

    bash 脚本中使用sed

    #!/usr/bin/env bash
    
    n=1 
    while read -r line; do 
        sed -i.bak "s/spark-worker/&-$n/" <<< "$line"
        if [[ "$line" =~ "spark-worker" ]]; then 
            n=$(( n+1 )) 
        fi
    done < input_file
    

    或者作为一个班轮

    $ n=1; while read -r line; do sed "s/spark-worker/&-$n/" <<< "$line"; if [[ "$line" =~ "spark-worker" ]]; then n=$(( n+1 )); fi; done < input_file
    [master]
    spark-master ansible_ssh_host=ec2-3-236-23-XXX.compute-1.amazonaws.com
    
    [worker]
    spark-worker-1 ansible_ssh_host=ec2-34-204-206-XXX.compute-1.amazonaws.com
    spark-worker-2 ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
    .
    .
    spark-worker-3 ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
    
    [spark_cluster:children]
    master
    worker
    

    或使用awk

    awk -v work="spark-worker" '$0~work{n++; gsub(work,work"-"n)}1' input_file
    [master]
    spark-master ansible_ssh_host=ec2-3-236-23-XXX.compute-1.amazonaws.com
    
    [worker]
    spark-worker-1 ansible_ssh_host=ec2-34-204-206-XXX.compute-1.amazonaws.com
    spark-worker-2 ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
    .
    .
    spark-worker-3 ansible_ssh_host=ec2-3-238-204-XXX.compute-1.amazonaws.com
    
    [spark_cluster:children]
    master
    worker
    

    【讨论】:

    • 工作就像一个魅力,但我如何让它编辑文件而不只是提示它到标准输出?
    • 如果文件很大,为文件中的每一行运行sed 的副本可能会很昂贵。对于小文件,这不是问题。我猜截止尺寸在 50-500 行范围内。就个人而言,我会使用(一份)awk,这样会更简单、更快。确实,sed 不是这项工作的正确工具——Awk、Perl、Python ……任何强大的脚本语言都可以更巧妙地完成这项工作。
    • @ShaharHamuzimRajuan 请检查编辑。添加了 -i 标志,用于使用 .bak 进行就地编辑以同时进行备份
    • @JonathanLeffler 确实如此。 OP 要求提供sed/bash 解决方案,以便最初提供。还添加了awk 解决方案
    • @HatLess 您不能使用sed -i 处理来自变量的字符串。它只能直接在文件上运行,您不希望在此处这样做,因为它会将编辑应用于所有行,而不仅仅是当前正在操作的行。
    【解决方案3】:

    这可能对你有用(GNU sed):

    sed -E 's/spark-worker/&-\n/g;T
            :a;x;s/.*/echo $((&+1))/e;x;G;s/\n(.*)\n(.*)/\2\1/;/\n/ba' file
    

    通过设置-E 命令行选项打开扩展正则表达式。

    将所有出现的字符串spark-worker 替换为- 和换行符。

    如果没有发生替换,则不对当前行执行进一步处理。

    否则,通过评估 bash shell echo 命令在保持空间中增加一个计数器,将计数器附加到当前行,然后将该计数器附加到所需字符串的第一次出现以及是否有更多出现,重复直到没有更多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      • 2014-11-14
      • 2017-02-07
      相关资源
      最近更新 更多