Awk 移位空格

Awk 移位空格,awk,sed,perl,Awk,Sed,Perl,考虑这个文件 $ cat infile.txt 1111 2222 3333 4444 请注意,每行至少有2个前导空格。我想 将所有行均匀向左移动,直到至少一行没有前导空格, 范例 现在在这种情况下,这意味着所有的东西都离开了2个空间,但是 解决方案需要处理可能需要更多或更少的其他文件 移动。如果可能,请使用awk或sed执行此任务。我试过这个 awk '(sub(" ",""))' infile.txt 但是,如果一行最初少于2个空格,它将不起作用。使用: 在

考虑这个文件

$ cat infile.txt
  1111
    2222
      3333
  4444
请注意,每行至少有2个前导空格。我想 将所有行均匀向左移动,直到至少一行没有前导空格, 范例

现在在这种情况下,这意味着所有的东西都离开了2个空间,但是 解决方案需要处理可能需要更多或更少的其他文件 移动。如果可能,请使用awk或sed执行此任务。我试过这个

awk '(sub("  ",""))' infile.txt
但是,如果一行最初少于2个空格,它将不起作用。

使用:

在脚本中:

#!/usr/bin/env perl
use strict; use warnings;

my $len;

while (<>) {
    if ($. == 1) {
        (my $spaces = $_ ) =~ s/^(\s+).*/$1/;
        $len = (length $spaces) - 1;
    }
    print substr $_, $len;
}
使用:

在脚本中:

#!/usr/bin/env perl
use strict; use warnings;

my $len;

while (<>) {
    if ($. == 1) {
        (my $spaces = $_ ) =~ s/^(\s+).*/$1/;
        $len = (length $spaces) - 1;
    }
    print substr $_, $len;
}

这是一个
awk

awk -F"[^ ]" '!NF {next} {s=length($1);a[NR]=$0} min>s||NR==1 {min=s} END {for (i=1;i<=NR;i++) print substr(a[i],min+1)}' file
1111
  2222
    3333
4444
awk-F“[^]”!NF{next}{s=length($1);a[NR]=0}min>s | | NR==1{min=s}END{for(i=1;is | | NR==1{
min=s}
结束{

对于(i=1;i这里是一个
awk

awk -F"[^ ]" '!NF {next} {s=length($1);a[NR]=$0} min>s||NR==1 {min=s} END {for (i=1;i<=NR;i++) print substr(a[i],min+1)}' file
1111
  2222
    3333
4444
awk-F“[^]”!NF{next}{s=length($1);a[NR]=$0}min>s | NR==1{min=s}END{for(i=1;is | NR==1{
min=s}
结束{
对于(i=1;i
  • 自适应于空间数,但不考虑空(或仅空间)行
  • 假设未使用
    ³
    (用作分隔符,但可以使用另一个字符)
  • 对大型文件无效(在内存缓冲区中加载文件两次,并递归多次替换)
感谢@potong对不同bug或简单算法的有用评论

  • 自适应于空间数,但不考虑空(或仅空间)行
  • 假设未使用
    ³
    (用作分隔符,但可以使用另一个字符)
  • 对大型文件无效(在内存缓冲区中加载文件两次,并递归多次替换)

感谢@potong对不同bug或简单算法的有用评论

我理解您需要左移两个空格的倍数

我尝试使用sed和shell使其尽可能简短:

#while there is no line beginning with 0 spaces
while ! grep "^ \?[^ ]" infile.txt > /dev/null; do 
    #on each line of the file remove the first spaces
    sed -i "s/^  //"  infile.txt ;
done
注1: grep指令与空行不匹配。因此空行不被视为未移位行

您可能希望grep匹配空行:“^\?[^]\\\\^$”

注2: 空文件,将使while循环无限。 您可能需要使用grep-v“^”,在这种情况下:空行被视为未移位

请注意,您可以创建infle.txt的副本,而不是使用它


我确信可以将while循环和grep转换成一些sed指令。但是您必须将sed缓冲区中的所有行连接起来,这不是它的正常用途。

我知道您需要有一个左移的2倍空格

我尝试使用sed和shell使其尽可能简短:

#while there is no line beginning with 0 spaces
while ! grep "^ \?[^ ]" infile.txt > /dev/null; do 
    #on each line of the file remove the first spaces
    sed -i "s/^  //"  infile.txt ;
done
注1: grep指令与空行不匹配。因此空行不被视为未移位行

您可能希望grep匹配空行:“^\?[^]\\\\^$”

注2: 空文件,将使while循环无限。 您可能需要使用grep-v“^”,在这种情况下:空行被视为未移位

请注意,您可以创建infle.txt的副本,而不是使用它

我确信可以将while循环和grep转换成一些sed指令。但是您必须将sed缓冲区中的所有行连接起来,这不是它的正常用途。

这可能适合您(GNU-sed):

感谢NeronLeVelu,我刚刚整理了他的解决方案。

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

感谢NeronLeVelu,我刚刚整理了他的解决方案。

一种方法,使用AWK:

awk 'FNR==NR {
    x = length($0)
    sub(/^ */, "")
    y = x - length($0)
    if (r > y || NR==1) r = y
    next
}{
    print substr($0, r + 1)
}' infile.txt{,}
此解决方案读取输入文件两次:

  • 在第一次读取时,确定最大允许缩进水平
  • 在第二次读取时,以确定的偏移量打印该行
    • 单向,使用AWK:

      awk 'FNR==NR {
          x = length($0)
          sub(/^ */, "")
          y = x - length($0)
          if (r > y || NR==1) r = y
          next
      }{
          print substr($0, r + 1)
      }' infile.txt{,}
      
      此解决方案读取输入文件两次:

      • 在第一次读取时,确定最大允许缩进水平
      • 在第二次读取时,以确定的偏移量打印该行
        • 另一个(G)awk

          读取文件两次(内存不足)

          输出

            1111 1111
              2222 2222
                3333 3333
            4444 4444
          
          1111 1111
            2222 2222
              3333 3333
          4444 4444
          
          另一个(G)awk

          读取文件两次(内存不足)

          输出

            1111 1111
              2222 2222
                3333 3333
            4444 4444
          
          1111 1111
            2222 2222
              3333 3333
          4444 4444
          

          第一行总是有最小的初始空白吗?或者你必须搜索整个文件才能找到它吗?我在你的预期结果中注意到..这些行有多个前导空格..这是正确的吗?因为你想要没有前导空格的行吗?第一行总是有最小的初始空白吗?还是do您必须搜索整个文件才能找到它?我在您的预期结果中注意到..这些行有多个前导空格..这是否正确?因为您需要不带前导空格的行?posix版本上的特殊字符比较敏感(我使用AIX sed)因此,字符的十六进制、八进制和十进制定义,有时传统的
          \n
          不起作用。在GNU上,使用类似
          [^\n]的模式会更容易
          按原样,此解决方案返回错误的结果。可能
          -n
          开关已被忽略,或者最后一个命令应为
          ;d
          。此外,如果重新考虑替换命令,我相信不需要使用
          ³
          字符(这将删除已经引入的另一个bug,即当3行换行时会发生什么?)最后<代码> h <代码>插入一个换行符,然后附加PATN缓冲器,考虑第一行吗?对,我忘记-N(修正后感谢)。以及其他一些关于起始空间问题的评论。谢谢你,也为糟糕的编码感到抱歉。特殊字符在posix版本(我使用AIX sed)上比较敏感,所以字符的十六进制、八进制和十进制定义,有时传统的
          \n
          不起作用。在GNU sed上,使用类似
          [^\n]的模式会更容易
          按原样,此解决方案返回错误的结果。可能
          -n
          开关已被忽略,或者最后一个命令应为
          ;d
          。此外,我认为如果y,则不需要使用
          ³
          字符
          1111 1111
            2222 2222
              3333 3333
          4444 4444