转移空白

时间:2014-12-23 08:24:25

标签: awk sed

考虑这个文件

$ cat infile.txt
  1111
    2222
      3333
  4444

请注意,每行至少有2个前导空格。我想要 将所有线均匀地移动,直到至少一条线没有前导空格, 示例

$ cat outfile.txt
1111
  2222
    3333
4444

现在在这种情况下,这意味着将一切都留下2个空格,但是 解决方案需要使用可能需要更多或更少的其他文件 移动。如果可能,请使用awk或sed执行此任务。我试过这个

awk '(sub("  ",""))' infile.txt

但是如果一条线最初的空间少于2个,它将不起作用。

7 个答案:

答案 0 :(得分:2)

这可能适合你(GNU sed):

sed -r 'H;$!d;x;:a;/\n+\S/!s/(\n+) /\1/g;ta;s/.//' file

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

答案 1 :(得分:1)

这是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;i<=NR;i++)
        print substr(a[i],min+1)}
' file

通过将字段分隔符设置为"[^ ]"(不是空格),第一个字段将包含空格组 这种方式length($1)给出了文本前面的空格数,无论文本中是否有更多空格。

答案 2 :(得分:1)

sed '#n
H;${x
:cycle
   h
:nld
   s/\(\n\)\1/\1 \1/g;t nld
   s/\(n\)$/\1 /

   /\n[^ ]/ !{
      s/\(\n\)[ ]/\1/g
      b cycle
      }
   x
   s/.//p
   }' YourFile
  • 自动适应空间数量但不处理空(或仅空格)线
  • 假设未使用³(用作分隔符,但可以使用其他字符)。
  • 在大文件上效率不高(在内存缓冲区加载文件两次,多次递归替换)

感谢@potong关于不同错误的所有有用的评论或简单的algorythm

答案 3 :(得分:1)

另一个(G)awk

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

awk '{a=(x=match($0,/[^ ]/))<a||!a?x:a}FNR!=NR{print substr($0,a)}' file{,}

检查第一个空格是否存储并存储。
然后在第二个文件上打印从存储的最低值开始的行的子行。

一次读取文件(使用大量内存)

 awk '{a=(x=match(b[NR]=$0,/[^ ]/))<a||!a?x:a}END{while(++i<=NR)print substr(b[i],a)}' file

与第一行相同,除了每行存储在一个数组中,并且打印数组中每行的子字符串。

例如

input

  1111 1111
    2222 2222
      3333 3333
  4444 4444

output

1111 1111
  2222 2222
    3333 3333
4444 4444

答案 4 :(得分:0)

使用

脚本中的

#!/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;
}

或在命令行中:

$ perl -ne '
    $. == 1 and do{
        (my $spaces = $_ ) =~ s/^(\s+).*/$1/;
        $len = (length $spaces) - 1;
    };
    print substr $_, $len
' file

答案 5 :(得分:0)

我知道您需要左移 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: 空文件,会使循环无限。 你可能想要使用grep -v“^”,在这种情况下:空行被认为没有移位。

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

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

答案 6 :(得分:0)

一种方法,使用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{,}

此解决方案两次读取输入文件:

  • 在第一次阅读时,确定允许的最大缩进级别
  • 在第二次读取时,以确定的偏移量打印行