sed命令用于删除文件中的两个后续行

时间:2015-02-20 09:33:26

标签: design-patterns sed lines

我的文件包含

等行
GRANT SELECT ON USER.TABLE1 TO USER1
/
GRANT INSERT ON USER.TABLE1 TO USER1
/
GRANT UPDATE ON USER.TABLE1 TO USER1
/
GRANT DELETE ON USER.TABLE1 TO USER1
/
GRANT SELECT ON USER.TABLE1 TO USER2
/
GRANT INSERT ON USER.TABLE1 TO USER2
/
GRANT UPDATE ON USER.TABLE1 TO USER2

......等等......

sed命令我正在寻找或者更好地寻找穿过两条线的模式, 应该删除" GRANT .."行加上后来的行以" /"。

开头

你们的任何解决方案都是大师吗?

3 个答案:

答案 0 :(得分:2)

sed '/^GRANT/ { N; d }' filename

当遇到以GRANT开头的行时,会获取下一行并弃掉它们。

仅在下一行以GRANT开头时删除/行,

sed ':a /^GRANT/ { N; /\n\//! { P; s/.*\n//; ba }; d }' filename

的工作原理。这很复杂,主要是因为两条GRANT行可能会一个接一个地直接出现,如

GRANT foo
GRANT bar
/

必须删除GRANT bar/并且GRANT foo保持不变:

:a            # jump label for looping
/^GRANT/ {    # if a line begins with GRANT
  N           # fetch the next line
  /\n\//! {   # if the next line does not begin with /
    P         # print the first
    s/.*\n//  # remove it
    ba        # go back to :a
  }
  d           # otherwise discard both
}

或者,在将文件完全读入内存后使用多行正则表达式(假设它适合那里):

sed ':a $!{N; ba}; s/\(^\|\n\)GRANT[^\n]*\n\/[^\n]*//g' filename

,其中

:a $!{N; ba}                          # read whole file into the pattern space
 s/\(^\|\n\)GRANT[^\n]*\n\/[^\n]*//g  # match offending lines by regex and
                                      # remove them

但是,在这一点上,我认为最常见的选择是在多线模式下使用pcregrep

pcregrep -vM '^GRANT[^\n]*\n/' filename

答案 1 :(得分:0)

awk应该有效:

awk '/^GRANT/ {f=1;next} f && /^\// {f=0;next} 1' file

如果以^GRANT开头的行,请跳过它并将标记f设置为true 如果行以/开头且标记f为真,则跳过它并重置标记f
1打印所有其他行。

因此,这只会删除以GRANT开头的行以及以/开头的下一行

示例:

cat file
GRANT SELECT ON USER.TABLE1 TO USER1
/
GRANT INSERT ON USER.TABLE1 TO USER1
test
/ should be removed
some other data
/ should not be removed
GRANT UPDATE ON USER.TABLE1 TO USER1
/
GRANT DELETE ON USER.TABLE1 TO USER1
/
GRANT SELECT ON USER.TABLE1 TO USER2
/
GRANT INSERT ON USER.TABLE1 TO USER2
/
GRANT UPDATE ON USER.TABLE1 TO USER2

awk '/GRANT/ {f=1;next} f && /^\// {f=0;next} 1' file
test
some other data
/ should not be removed

答案 2 :(得分:0)

sed用于单行操作。对于跨越线条的任何东西,你应该使用awk。例如使用GNU awk进行多字符RS:

awk -v RS='^$' -v ORS= '{gsub(/GRANT[^\n]+\n[/]\n/,"")}1' file

e.g:

$ cat file
foo
GRANT INSERT ON USER.TABLE1 TO USER1
/
GRANT UPDATE ON USER.TABLE1 TO USER1
intermediate line so leave
/
GRANT DELETE ON USER.TABLE1 TO USER1
/
bar

$ awk -v RS='^$' -v ORS= '{gsub(/GRANT[^\n]+\n[/]\n/,"")}1' file
foo
GRANT UPDATE ON USER.TABLE1 TO USER1
intermediate line so leave
/
bar