【问题标题】:repeating the text many times多次重复文本
【发布时间】:2021-10-18 19:06:03
【问题描述】:

我想重复输入文本 5 次,并想保存在另一个文本文件中。但是在每次重复中,第一行和最后一行的编号只需要更改。

我的输入文字是:

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

输出:

READ 1 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 1A ALL

READ 2 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 2A ALL

READ 3 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 3A ALL

READ 4 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 4A ALL

READ 5 ALL
DMN 2,3 ^DTND
DEL 2,3
WRITE 5A ALL

我试过了

#!/bin/sh
for file in `cat input.txt`
do
yes $file
done

【问题讨论】:

    标签: linux bash for-loop awk


    【解决方案1】:

    你可以用 Perl 做到这一点:

    echo 'READ %s ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE %sA ALL' | perl -0777 -nE '
    for($x=1; $x<=5; $x++) { say sprintf $_, $x, $x }'
    

    或者在 awk 中:

    echo 'READ %s ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE %sA ALL' | awk -v RS= '{for(i=1;i<=5;i++) printf($0 "\n\n",i,i)}'
    

    shell 中的相同概念:

    s='READ %s ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE %sA ALL'
    
    for i in {1..5}; do
        printf "$s\n\n" "$i" "$i"
    done    
    

    如果您不想为 printf 创建模板以与 %s 一起使用以进行替换,我会使用 perl 来获得更精确的正则表达式:

    echo 'READ 1 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 1A ALL' | perl -0777 -nE '
    for($x=1; $x<=5; $x++) { 
        $s=$_; 
        $s=~s/^(READ |WRITE )(1)(?=\D|$)/$1$x/g; 
        say $s }'
    

    【讨论】:

    • 能否请您查看我的回答。
    【解决方案2】:

    将 GNU awk 用于gensub()

    $ awk -v RS= -v ORS='\n\n' '{for (i=1; i<=5; i++) print gensub(/1/,i,"g")}' file
    READ 1 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 1A ALL
    
    READ 2 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 2A ALL
    
    READ 3 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 3A ALL
    
    READ 4 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 4A ALL
    
    READ 5 ALL
    DMN 2,3 ^DTND
    DEL 2,3
    WRITE 5A ALL
    

    【讨论】:

      【解决方案3】:

      for file in `cat input.txt` 循环输入文件中的单词。

      yes $file 将永远输出单词,因此您的循环将永远不会重复。

      使用for 循环将索引从1 增加到5。然后使用sed 将其替换到文件的第一行和最后一行。

      for i in {1..5}; do
          sed -e "s/(READ ).*( ALL)/\\1$i\\2/" -e "s/(WRITE ).*(A ALL)/\\1$i\\2/" input.txt
      done
      

      【讨论】:

        【解决方案4】:

        假设您只想替换字符串中的第一个和最后一个1,这是一个 gnu-awk 解决方案:

        awk -v RS= '
        {
           print
           for (i=2; i<=5; ++i)
              print gensub(/^([^1]*)1(.*)1([^1]*)$/, "\\1" i "\\2" i "\\3", "1")
        }' ORS='\n\n' file
        
        READ 1 ALL
        DMN 2,3 ^DTND
        DEL 2,3
        WRITE 1A ALL
        
        READ 2 ALL
        DMN 2,3 ^DTND
        DEL 2,3
        WRITE 2A ALL
        
        READ 3 ALL
        DMN 2,3 ^DTND
        DEL 2,3
        WRITE 3A ALL
        
        READ 4 ALL
        DMN 2,3 ^DTND
        DEL 2,3
        WRITE 4A ALL
        
        READ 5 ALL
        DMN 2,3 ^DTND
        DEL 2,3
        WRITE 5A ALL
        

        【讨论】:

          【解决方案5】:

          不使用 Bash 以外的程序/进程:

          repeat_file() {
            local -ir times="${1}"
            local -a lines first_line last_line
            readarray -t lines
            ((${#lines[@]} >= 2)) || return 2
            read -a first_line <<<"${lines[0]}"
            read -a last_line <<<"${lines[-1]}"
            unset 'lines[-1]'
            unset 'lines[0]'
            local -ar lines
            local -i idx
            local line
            for ((idx = 1;;)); do
              echo "${first_line[@]}"
              for line in "${lines[@]}"; do
                echo "${line}"
              done
              echo "${last_line[@]}"
              ((++idx > times)) && break
              ((++first_line[1]))
              last_line[1]="$(("${last_line[1]%A}" + 1))A"
              echo
            done
          }
          
          repeat_file 5 < input > output
          

          【讨论】:

            【解决方案6】:

            另一个 Perl 解决方案:

            更新答案(感谢 dawg)

            echo 'READ 1 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 1A ALL' | perl -0777 -nE 'while($i++<5) { s/(\d)(?=A? ALL)/$i/g; say }'
            

            原答案

            $ echo 'READ 1 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 1A ALL' | perl -0777 -nE ' $_.="\n"; print; 
            while($i++<=3) { s/(\d)(?=A? ALL)/$1+1/ge; print } '
            

            两个打印:

            READ 1 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 1A ALL
            
            READ 2 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 2A ALL
            
            READ 3 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 3A ALL
            
            READ 4 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 4A ALL
            
            READ 5 ALL
            DMN 2,3 ^DTND
            DEL 2,3
            WRITE 5A ALL
            

            【讨论】:

            • 在这种情况下当然可以。我认为e 的使用并不是真正必要的,我会引导您使用perl -0777 -nE 'while($i++&lt;5) { s/(\d)(?=A? ALL)/$i/g; say }'
            • aah.. 很好,我不喜欢有 2 个打印声明.. 你修好了.. 非常感谢..
            • @dawg.. 在stackoverflow.com/questions/68868817/… 上需要您的帮助,您能查看一下并提出改进建议吗?
            猜你喜欢
            • 2015-11-12
            • 1970-01-01
            • 2018-04-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-01-01
            相关资源
            最近更新 更多