与我发布的问题类似这里之前,我正在寻找一个 Linux 命令帮助,它执行以下操作,与我最初的问题有细微的差别:
--
在给定文件中不区分大小写地搜索特定的单词或短语,然后在紧接着的“n”行中插入或添加字符(在本例中为 SQL 注释)作为前缀包括给定文件中匹配单词或短语的行。
例子:
如果我尝试不区分大小写地搜索短语“CREATE FUNCTION plpgsql_call_handler”,并且如果它与行号 102644 匹配,那么我希望--
在给定文件中的行号 102644 和紧接着的 2 行中插入/添加前缀字符。在这种情况下,我希望在行号 102644、102645、102646 中插入/添加前缀字符--
。
示例文件:
102644 CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler
102645 AS '/usr/lib/pgsql/plpgsql.so', 'plpgsql_call_handler'
102646 LANGUAGE c;
我希望/希望它被改变成(在这种情况下,它是一个 SQL 注释):
102644 -- CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler
102645 -- AS '/usr/lib/pgsql/plpgsql.so', 'plpgsql_call_handler'
102646 -- LANGUAGE c;
答案1
您可以这样使用 sed 来执行此操作:
sed -r -i -e '/CREATE FUNCTION plpgsql_call_handler/I,+2 s/^/-- /'
(可能需要 GNU sed。)
将 2 替换为您想要的行数(或使用任何其他 sed 地址形式)。
这比那个 perl 怪物要简单得多。此外,perl 也可以通过使用以下方法就地完成此操作-i
:
perl -i -n -e horrible_perl_code /path/to/file
在这两种情况下,如果您希望保留备份,请更改-i
为-i.bak
。
答案2
再一次,老式的瑞士军用电锯开始运转:
perl -n -e 'if (/create/i) { s/^(\d+)/\1 --/; print $_; $_=<> ; s/^(\d+)/\1 --/; print $_; $_=<> ; s/^(\d+)/\1 --/; print $_; } else { print $_; }' < /path/to/file
它并不像看上去那么可怕! perl -n -e
对文件中的每一行进行循环,而不是隐式打印该行,而是在每一行上运行所提供的小型 perl 脚本。
提供的小脚本在每一行中查找一个字符串(这里是create
,但您可以根据需要更改它),不区分大小写地匹配(/i
)。当它找到字符串时,它会:
- 将行首所有直接连续的数字 (
^(\d+)
) 替换为其自身 (\1
) 加“--”, - 打印修改后的行
- 读入 ( ) 中的下一行
$_=<>
并对该行重复步骤 1 和 2 - 读入下一行并对该行重复步骤 1 和 2
如果该行不包含该字符串,则不加修改地打印它。
我确信这可以进一步优化,但希望它能满足您的要求。它将修改后的文件发送到 STDOUT;将其捕获到临时文件并将其移动到原始文件上,这留给 OP 做(微不足道的)练习!
答案3
AWK 示例:
awk 'tolower($0) ~ /create function plpgsql_call_handler/ {n=3;} // { if (n-->0) printf "-- "; print $0;}'