Bash 如何使用可能有新行的输入,每n个字符插入一个模式?

Bash 如何使用可能有新行的输入,每n个字符插入一个模式?,bash,perl,awk,sed,Bash,Perl,Awk,Sed,我试图使用sed每隔2000个字符向文件中插入一个模式。我正在使用这个sed命令,但是如果文件中有多行,它就不起作用,因为计数会在每一行上重置 模式:' ||“ sed "s/.\{2000\}/&'\n || '/g" file 如何使此命令与可能有或可能没有新行的输入一起工作?我同意非sed解决方案 下面是一个示例,它是每4个字符而不是每2000个字符插入一个模式 输入示例: aaaaaa bbbbbb 示例输出: aaaa' || 'aa b' || 'bbbb' ||

我试图使用sed每隔2000个字符向文件中插入一个模式。我正在使用这个sed命令,但是如果文件中有多行,它就不起作用,因为计数会在每一行上重置

模式:
'
||“

sed "s/.\{2000\}/&'\n || '/g" file
如何使此命令与可能有或可能没有新行的输入一起工作?我同意非sed解决方案

下面是一个示例,它是每4个字符而不是每2000个字符插入一个模式

输入示例:

aaaaaa
bbbbbb
示例输出:

aaaa'
 || 'aa
b'
 || 'bbbb'
 || 'b
  • 计数4个字符(4个a),插入模式
  • 计数4个字符(2个a、新行字符和1个b),插入模式
  • 计数4个字符(4个b),插入模式
  • 只剩下1个字符(1b)

  • 谢谢。

    这个
    gnu awk
    可以:

    echo "abcdefghijkl" | awk -v FS= -v OFS= '{for (i=1;i<=NF;i++) if (i>1 && i%3==1)  $i="\n ||"$i}1'
    abc
     ||def
     ||ghi
     ||jkl
    
    echo“abcdefghijkl”| awk-vfs=-vofs='{for(i=1;i1&&i%3==1)$i=“\n | |“$i}1”
    abc
    ||def
    ||ghi
    ||jkl
    
    对于您的文件,每1000个字符

    awk -v FS= -v OFS= '{for (i=1;i<=NF;i++) if (i>1 && i%1000==1)  $i="\n ||"$i}1' file
    
    awk-vfs=-vofs='{for(i=1;i1&&i%1000==1)$i=“\n | |”$i}1”文件
    
    更新的解决方案:

    awk -v FS= -v OFS= '{for (i=1;i<=NF;i++) if (i>1 && i%4==1)  $i="\x27\\n || \x27"$i;printf "%s\x27\\n || \x27",$0} END {print ""}' file
    aaaa'\n || 'aa'\n || 'bbbb'\n || 'bb'\n || '
    
    awk-vfs=-vofs='{for(i=1;i1&&i%4==1)$i=“\x27\\n | | \x27”$i;printf”%s\x27\\n | | \x27“,$0}END{print”“}文件
    aaaa'\n | |'aa'\n | | |'bbbb'\n | | |'bb'\n | | |'
    
    有一个特殊的Linux命令,用于按指定参数拆分文件

    阅读有关csplit命令的详细信息。

    perl-0777pe“s/(.{2000})/\$1'\n | |'/gs”文件

    • -0777
      将整个文件作为一行处理
    • \$1
      允许引用捕获不带shell的组,使其为空,因为我必须使用双引号
    • s///gs
      使用
      g
      重复多次,并使用
      s
      确保
      {4}
      可以跨越换行符
    $printf“aaaaa\nbbbbbb\n”| perl-0777pe“s/(.{4})/\$1'\n | |'/gs” aaaa' ||“aa b' ||“bbbb” ||”“b
    这里是一种通用的方法,我们可以给出要插入字符串的字符数。使用GNU
    awk
    RS
    FS
    gsub
    功能。使用GNU
    awk
    进行测试,并且仅使用提供的示例。(好的,我刚刚测试了在5个字符后插入新字符,而且效果非常好:)

    添加一种非线性形式的解决方案:

    输出如下:



    上述代码说明:添加上述代码的完整说明

    awk -v noc="4" -v char="\047\n || \047" -v RS="" -v FS="\n" '  ##Mentioning noc=4 for number of characters after which we want to insert new character\
                                                                   ## , mentioning char variable with value which OP wants to insert. \
                                                                   ##  Making RS NULL here, making FS as new line here for all lines of Input_file
    {
      num=num==noc?(noc-1):noc                                     ##Creating variable num whose value is noc-1 when it is 4 and 4 when it is NOT 4.
      gsub(".{"num"}","&" char)                                    ##Using gsub function to give number of characters which need to be substitutes with new char here.
    }
    1                                                              ##Mentioning 1 will print edited/non-edited line of Input_file.
    '  Input_file                                                  ##Mentioning Input_file name here.
    

    GNU awk用于多字符RS,并且一次只将4个字符读入内存(与其他一些解决方案需要将整个文件一次读入内存不同):


    以下sed解决方案将起作用(使用四个字符,而不是2000个字符):

    说明:

    • H;1h;\$!Dx
      将整个文件读入模式缓冲区(请参阅)
    • s/\{4\}/&'\n| |'/g
      在每四个字符后添加所需的文本
    在bash中,我们需要转义美元符号,
    \$
    ,因为替换模式包含单引号,所以使用双引号将sed字符串括起来更容易

    编辑:如Ed Morton在评论中所述,与其使用双引号并转义
    $
    ,另一种方法是使用单引号并将每个嵌入的单引号
    '
    替换为
    '\'
    ,以获得:

      sed 'H;1h;$!d;x;s/.\{4\}/&'\''\n || '\''/g'
    

    请将示例输入(无描述、无图像、无链接)和该示例输入的所需输出添加到您的问题中(无注释)。使用GNU sed,您可以使用
    sed-z“s/\{2000\}/&'\n| |'/g”文件
    。但是,换行符将被计为单独的字符。添加了示例输入@WiktorStribiżew解决方案运行完美,但遗憾的是,我的gnu版本是4.2.1,在4.2.2中添加了对-z的支持。更新了我的解决方案。PS您的输出中确实缺少a
    b
    (应该是6
    b
    )为什么您得到
    aa\nb'\n
    没有4个字母?您能解释一下新行应该发生什么吗。计数应该从0开始,还是从前一行的剩余数字开始?使用八进制而不是十六进制来表示
    '
    。看见此外,与发布的预期输出相比,最终脚本在
    'aa
    之后缺少
    \nb
    ,并在输出的末尾显示一个额外的
    b'\n |
    。@EdMorton感谢\047提示。OP多次更改请求,我已经放弃解决它。不客气,是的,我有一种感觉,可能就是这样!使用这种双重引用脚本的方法,您还需要转义
    在设置了一些历史选项的某些Shell中。除非您需要双引号以避免陷入“逃逸”地狱-
    sed'H,否则在字符串和脚本周围始终使用单引号;1h;$!Dx;s/\{4\}/&\''''''\n | |'\''/g'文件
    。当然,我并不建议您为此实际使用sed。很好,vs
    perl-0777
    sed-z
    awk-v RS=“”
    当文件中没有空行时(如果有空行,这种方法将失败)或
    gawk-v RS='^$'
    ,我目前在任何答案中都没有看到,但可能会出现。
    awk -v noc="4" -v char="\047\n || \047" -v RS="" -v FS="\n" '
    {
      num=num==noc?(noc-1):noc
      gsub(".{"num"}","&" char)
    }
    1
    '  Input_file
    
    aaaa'
     || 'aa
    b'
     || 'bbbb'
     || 'b
    
    awk -v noc="4" -v char="\047\n || \047" -v RS="" -v FS="\n" '  ##Mentioning noc=4 for number of characters after which we want to insert new character\
                                                                   ## , mentioning char variable with value which OP wants to insert. \
                                                                   ##  Making RS NULL here, making FS as new line here for all lines of Input_file
    {
      num=num==noc?(noc-1):noc                                     ##Creating variable num whose value is noc-1 when it is 4 and 4 when it is NOT 4.
      gsub(".{"num"}","&" char)                                    ##Using gsub function to give number of characters which need to be substitutes with new char here.
    }
    1                                                              ##Mentioning 1 will print edited/non-edited line of Input_file.
    '  Input_file                                                  ##Mentioning Input_file name here.
    
    $ awk -v RS='.{4}' '{printf "%s", (RT=="" ? $0 : RT "\047\n || \047")}' file
    aaaa'
     || 'aa
    b'
     || 'bbbb'
     || 'b
    
      sed "H;1h;\$!d;x;s/.\{4\}/&'\n || '/g"
    
      sed 'H;1h;$!d;x;s/.\{4\}/&'\''\n || '\''/g'