awk sed根据前一行替换行上的空格

时间:2017-10-31 03:01:11

标签: awk sed

我有一个看起来像这样的文件,这是Windows命令icacls c的结果:\ path / t> output.txt

    C:\temp\2\ok Everyone:(I)(RX)
                 BUILTIN\Administrators:(I)(F)
                 NT AUTHORITY\SYSTEM:(I)(F)
                 BUILTIN\Users:(I)(RX)
                 NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok.txt Everyone:(I)(RX)
                     BUILTIN\Administrators:(I)(F)
                     NT AUTHORITY\SYSTEM:(I)(F)
                     BUILTIN\Users:(I)(RX)
                     NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok1.txt Everyone:(I)(RX)
                      BUILTIN\Administrators:(I)(F)
                      NT AUTHORITY\SYSTEM:(I)(F)
                      BUILTIN\Users:(I)(RX)
                      NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok2.txt Everyone:(I)(RX)
                      BUILTIN\Administrators:(I)(F)
                      NT AUTHORITY\SYSTEM:(I)(F)
                      BUILTIN\Users:(I)(RX)
                      NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\test1.ps1 Everyone:(I)(RX)
                        BUILTIN\Administrators:(I)(F)
                        NT AUTHORITY\SYSTEM:(I)(F)
                        BUILTIN\Users:(I)(RX)
                        NT AUTHORITY\Authenticated Users:(I)(M)

我需要填充不完全为空的空白区域,并在其前面加上一行。好处是空白空间总是基于前一行的相同数量的字符。

期望的输出

    C:\temp\2\ok Everyone:(I)(RX)
    C:\temp\2\ok BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok BUILTIN\Users:(I)(RX)
    C:\temp\2\ok NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok.txt Everyone:(I)(RX)
    C:\temp\2\ok.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok.txt NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok1.txt Everyone:(I)(RX)
    C:\temp\2\ok1.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok1.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok1.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok1.txt NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok2.txt Everyone:(I)(RX)
    C:\temp\2\ok2.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok2.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok2.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok2.txt NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\test1.ps1 Everyone:(I)(RX)
    C:\temp\2\test1.ps1 BUILTIN\Administrators:(I)(F)
    C:\temp\2\test1.ps1 NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\test1.ps1 BUILTIN\Users:(I)(RX)
    C:\temp\2\test1.ps1 NT AUTHORITY\Authenticated Users:(I)(M)

我试过这样的事情: 为了获得两个文件并将它们粘贴在一起,但问题是意外的空间alwats螺旋顺序(我使用Windows awk和sed这就是我使用双引号的原因)

    awk  "{line=$2} {print NF?line:\"\"}" OUTPUT
    awk  "{line=$1} {print NF?line:\"\"}" OUTPUT
    awk -F":" "{line=$2} {print NF?line:\"\"}" OUTPUT
    awk -F":" "{line=$1} {print NF?line:\"\"}" OUTPUT

我将欣赏任何其他想法

5 个答案:

答案 0 :(得分:3)

awk救援!

awk '/^$/{k=""} !k{k=$1;$1=""} {sub(/^ +/,k FS)}1'


C:\temp\2\ok Everyone:(I)(RX)
C:\temp\2\ok BUILTIN\Administrators:(I)(F)
C:\temp\2\ok NT AUTHORITY\SYSTEM:(I)(F)
C:\temp\2\ok BUILTIN\Users:(I)(RX)
C:\temp\2\ok NT AUTHORITY\Authenticated Users:(I)(M)

C:\temp\2\ok.txt Everyone:(I)(RX)
C:\temp\2\ok.txt BUILTIN\Administrators:(I)(F)
C:\temp\2\ok.txt NT AUTHORITY\SYSTEM:(I)(F)
C:\temp\2\ok.txt BUILTIN\Users:(I)(RX)
C:\temp\2\ok.txt NT AUTHORITY\Authenticated Users:(I)(M)

C:\temp\2\ok1.txt Everyone:(I)(RX)
C:\temp\2\ok1.txt BUILTIN\Administrators:(I)(F)
C:\temp\2\ok1.txt NT AUTHORITY\SYSTEM:(I)(F)
C:\temp\2\ok1.txt BUILTIN\Users:(I)(RX)
C:\temp\2\ok1.txt NT AUTHORITY\Authenticated Users:(I)(M)

C:\temp\2\ok2.txt Everyone:(I)(RX)
C:\temp\2\ok2.txt BUILTIN\Administrators:(I)(F)
C:\temp\2\ok2.txt NT AUTHORITY\SYSTEM:(I)(F)
C:\temp\2\ok2.txt BUILTIN\Users:(I)(RX)
C:\temp\2\ok2.txt NT AUTHORITY\Authenticated Users:(I)(M)

C:\temp\2\test1.ps1 Everyone:(I)(RX)
C:\temp\2\test1.ps1 BUILTIN\Administrators:(I)(F)
C:\temp\2\test1.ps1 NT AUTHORITY\SYSTEM:(I)(F)
C:\temp\2\test1.ps1 BUILTIN\Users:(I)(RX)
C:\temp\2\test1.ps1 NT AUTHORITY\Authenticated Users:(I)(M)

您可能需要适应Windows格式。

答案 1 :(得分:1)

我讨厌自己所以我决定挑战自己用sed来解决它。结果完全可行:

$ cat /tmp/test.sed
h
:first
n
s/^\s*$/&/
t last
H
s/^//
t first
:last
x
:loop
s/^(.*)(Every.*)(\1[^\n]*)$/\1\2\3/
t break
s/(.*)(Every[^\n]*)((\n\1[^\n]*)*)\n\s*/\1\2\3\n\1/
t loop
:break
p
g
p

它肯定会达到结果:

$ sed -n -r -f /tmp/test.sed /tmp/try
    C:\temp\2\ok Everyone:(I)(RX)
    C:\temp\2\ok BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok BUILTIN\Users:(I)(RX)
    C:\temp\2\ok NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok.txt Everyone:(I)(RX)
    C:\temp\2\ok.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok.txt NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok1.txt Everyone:(I)(RX)
    C:\temp\2\ok1.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok1.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok1.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok1.txt NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok2.txt Everyone:(I)(RX)
    C:\temp\2\ok2.txt BUILTIN\Administrators:(I)(F)
    C:\temp\2\ok2.txt NT AUTHORITY\SYSTEM:(I)(F)
    C:\temp\2\ok2.txt BUILTIN\Users:(I)(RX)
    C:\temp\2\ok2.txt NT AUTHORITY\Authenticated Users:(I)(M)

我的神秘解决方案的解释如下:

h  # overwrite hold buffer with current line
:first  # set a label
n  # overwrite current line(pattern buffer) with next line
s/^\s*$/&/  # are we currently in blank line?
t last  # if so, we jump to :last, continue otherwise
H  # we append current line to hold buffer
s/^// # always true
t first  # so we will be going back to :first
:last
x  # so now we have all lines related to the single file. then we xchange the hold buffer to pattern buffer
:loop  # we need to loop to loop through all lines
s/^(.*)(Every.*)(\1[^\n]*)$/\1\2\3/  # have we substituted all lines yet?
t break  # if so, we break the loop, continue otherwise
s/(.*)(Every[^\n]*)((\n\1[^\n]*)*)\n\s*/\1\2\3\n\1/  # then we make sure each iteration will replace leading blanks with file path
t loop  # go back to the beginning of the loop
:break
p  # we print all we have now substituted
g  # get back the blank line
p  # print the blank line

此代码会自动调整任意行,例如此类形式的属性,只要它们用空行分隔即可。它不是太糟糕,不是吗?如果你愿意,请帮助我改进它。

答案 2 :(得分:0)

关注awk可以帮助您。

awk '/^C:\\/{val=$1;print;next} NF{sub(/^ +/,"");print val,$0;next} 1'  Input_file

在此处添加非单线形式的解决方案,但也有解释。

awk '
/^C:\\/{         ##Checking condition here if any line starts from C:\\, point to be noted here I am escaping \ for removing its special meaning.
 val=$1;         ##If any line starts from C:\\ then it will be come in this block, assigning variable named val to first field here.
 print;          ##Printing that specific line now.
 next            ##next is to skip all further statements from this line onwards and move the cursor to next line with starting of the statements.
}
NF{              ##Checking condition here if any line is NOT NULL so NF means number of fields and checking of number of fields variable is NOT NULL, if yes then do following.
 sub(/^ +/,"");  ##Substituting initial space with NULL in current line.
 print val,$0;   ##Printing variable named val and current line now.
next             ##Use next statement to skip further statements.
}
1                ##Mentioning 1 here to make the condition TRUE, so awk works on method of regexp and action, here I am making condition/regexp TRUE by mentioning 1 and not mentioning any action here so by default print of current line will happen.
' Input_file     ##Mentioning Input_file name here.

答案 3 :(得分:0)

或者甚至,如下所示,在预期输出中给出的开头有空格。

awk '{/C:/? s=$1 : NF ? $0 = s OFS $0 : ""; $1= "  "$1 }1' infile

测试结果:

$ cat infile
    C:\temp\2\ok Everyone:(I)(RX)
                 BUILTIN\Administrators:(I)(F)
                 NT AUTHORITY\SYSTEM:(I)(F)
                 BUILTIN\Users:(I)(RX)
                 NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok.txt Everyone:(I)(RX)
                     BUILTIN\Administrators:(I)(F)
                     NT AUTHORITY\SYSTEM:(I)(F)
                     BUILTIN\Users:(I)(RX)
                     NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok1.txt Everyone:(I)(RX)
                      BUILTIN\Administrators:(I)(F)
                      NT AUTHORITY\SYSTEM:(I)(F)
                      BUILTIN\Users:(I)(RX)
                      NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\ok2.txt Everyone:(I)(RX)
                      BUILTIN\Administrators:(I)(F)
                      NT AUTHORITY\SYSTEM:(I)(F)
                      BUILTIN\Users:(I)(RX)
                      NT AUTHORITY\Authenticated Users:(I)(M)

    C:\temp\2\test1.ps1 Everyone:(I)(RX)
                        BUILTIN\Administrators:(I)(F)
                        NT AUTHORITY\SYSTEM:(I)(F)
                        BUILTIN\Users:(I)(RX)
                        NT AUTHORITY\Authenticated Users:(I)(M)

输出:

$ awk '{/C:/? s=$1 : NF ? $0 = s OFS $0 : ""; $1= "  "$1 }1' infile
  C:\temp\2\ok Everyone:(I)(RX)
  C:\temp\2\ok BUILTIN\Administrators:(I)(F)
  C:\temp\2\ok NT AUTHORITY\SYSTEM:(I)(F)
  C:\temp\2\ok BUILTIN\Users:(I)(RX)
  C:\temp\2\ok NT AUTHORITY\Authenticated Users:(I)(M)

  C:\temp\2\ok.txt Everyone:(I)(RX)
  C:\temp\2\ok.txt BUILTIN\Administrators:(I)(F)
  C:\temp\2\ok.txt NT AUTHORITY\SYSTEM:(I)(F)
  C:\temp\2\ok.txt BUILTIN\Users:(I)(RX)
  C:\temp\2\ok.txt NT AUTHORITY\Authenticated Users:(I)(M)

  C:\temp\2\ok1.txt Everyone:(I)(RX)
  C:\temp\2\ok1.txt BUILTIN\Administrators:(I)(F)
  C:\temp\2\ok1.txt NT AUTHORITY\SYSTEM:(I)(F)
  C:\temp\2\ok1.txt BUILTIN\Users:(I)(RX)
  C:\temp\2\ok1.txt NT AUTHORITY\Authenticated Users:(I)(M)

  C:\temp\2\ok2.txt Everyone:(I)(RX)
  C:\temp\2\ok2.txt BUILTIN\Administrators:(I)(F)
  C:\temp\2\ok2.txt NT AUTHORITY\SYSTEM:(I)(F)
  C:\temp\2\ok2.txt BUILTIN\Users:(I)(RX)
  C:\temp\2\ok2.txt NT AUTHORITY\Authenticated Users:(I)(M)

  C:\temp\2\test1.ps1 Everyone:(I)(RX)
  C:\temp\2\test1.ps1 BUILTIN\Administrators:(I)(F)
  C:\temp\2\test1.ps1 NT AUTHORITY\SYSTEM:(I)(F)
  C:\temp\2\test1.ps1 BUILTIN\Users:(I)(RX)
  C:\temp\2\test1.ps1 NT AUTHORITY\Authenticated Users:(I)(M)

答案 4 :(得分:0)

让我们以其他方式尝试awk

awk '{
if(/^C:\\temp/) {x=$1;print}
else if(/[:alpha]/) {gsub(/^[ \t]+/," "); print x $0}
else print;     
}' ipfile