替换某行前的字符串

Mik*_*ike 6 sed perl text-processing

我有一个文件,如:

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );
Run Code Online (Sandbox Code Playgroud)

我想在包含 PRIMARY 的行之前的行中用 ')' 替换 ','。

结果应该是:

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Run Code Online (Sandbox Code Playgroud)

Siv*_*iva 9

使用GNU sed

sed  'N;s/,\(\s*\n.*PRIMARY\)/)\1/;P;D' file

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Run Code Online (Sandbox Code Playgroud)
  • N 将下一行输入读取/追加到模式空间中。
  • P 打印到当前模式空间的第一个嵌入换行符。
  • D 最多删除模式空间中第一个嵌入的换行符。开始下一个循环,但如果模式空间中仍有数据,则跳过从输入中读取。


gle*_*man 8

尝试反转文件,PRIMARY 之后的行上进行字符串替换,然后重新反转文件:

tac file | sed '/PRIMARY/ {n; s/,$/)/}' | tac
Run Code Online (Sandbox Code Playgroud)

  • +1 表示最聪明的方式。 (2认同)
  • @SivaPrasath - 不是真的,如果输入包含匹配`PRIMARY`的连续行,这将失败 (2认同)

pLu*_*umo 7

尝试这个,

perl -0777 -pe 's/,([^\n,]*\n[^\n]*PRIMARY)/)$1/g'
Run Code Online (Sandbox Code Playgroud)

这将取代过去,)的行之前的任何行,包括PRIMARY

解释

  • perl -0777 吞下整个文件(读作一行)
  • s/search_pattern/replacement/g 用全局替换替换搜索模式


ste*_*ver 5

如果您使用ed而不是sed您可以使用具有负偏移量的正则表达式地址:

g/PRIMARY/-1 s/,$/)/
Run Code Online (Sandbox Code Playgroud)

前任。

$ printf 'g/PRIMARY/-1 s/,$/)/\n,p\nq\n' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
Run Code Online (Sandbox Code Playgroud)

或(用于就地编辑)

printf 'g/PRIMARY/-1 s/,$/)/\nwq\n' | ed -s file
Run Code Online (Sandbox Code Playgroud)

替换将匹配的所有实例/PRIMARY/- 如果您只想替换第一个,请删除g修饰符。