简体   繁体   English

Perl命令行多行替换

[英]Perl command line multi-line replace

I'm trying to replace text in a multi-line file using command-line perl.我正在尝试使用命令行 perl 替换多行文件中的文本。 I'm using Ubuntu Natty.我正在使用 Ubuntu Natty。

Below is the content of my text file (called test.txt):以下是我的文本文件(称为 test.txt)的内容:

[mysqld]
#
# * Basic Settings
#

#
# * IMPORTANT
#   If you make changes to these settings and your system uses apparmor, you may
#   also need to also adjust /etc/apparmor.d/usr.sbin.mysqld.
#

user            = mysql
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
skip-external-locking

Below is my perl command:下面是我的 perl 命令:

perl -i -pe "s/(\[mysqld\][^\^]+)/\1\nsometext/g" test.txt

However, instead of replacing all the text in the file, below is what I end up with:但是,我没有替换文件中的所有文本,而是最终得到以下内容:

[mysqld]

sometext#
# * Basic Settings
#

#
# * IMPORTANT
#   If you make changes to these settings and your system uses apparmor, you may
#   also need to also adjust /etc/apparmor.d/usr.sbin.mysqld.
#

user            = mysql
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
skip-external-locking
#

I tried the Regex in RegexBuddy for Perl and it matches everything in the text file, but for some reason it's not working using perl on the command line.我在 RegexBuddy 中尝试了 Perl 的正则表达式,它匹配文本文件中的所有内容,但由于某种原因,它无法在命令行上使用 perl。

I'd appreciate some assistance.我会很感激一些帮助。

Thanks in advance.提前致谢。

You are reading the file line-by-line, so only the first line matches your regex.您正在逐行读取文件,因此只有第一行与您的正则表达式匹配。 What you'll want to do -- if you truly wish to delete most of the content -- is to slurp the file by using the -0 option, eg -0777 .你想要做的——如果你真的想删除大部分内容——是通过使用-0选项来删除文件,例如-0777 This is line ending processing, and 777 is just a number used by convention as an octal number large enough so as to cause file slurping.这是行结束处理,而777只是一个按惯例用作八进制数的数字,它足够大以导致文件 slurping。

perl -0777 -i -pe 's/(\[mysqld\][^\^]+)/$1\nsometext/g' test.txt

Also, I replaced your quotes.另外,我替换了你的引号。 If you are in *nix, which it seems you are, single quotes are preferable.如果你在 *nix 中,看起来你是,单引号是更可取的。 Case in point, $1 would not be interpolated by the shell.例如, $1不会被 shell 插值。

The -p switch causes Perl to iterate over every line of the input and execute the given code for each of them (and to print the lines afterwards). -p开关使 Perl 遍历输入的每一并为每一行执行给定的代码(然后打印这些行)。 Specifically, the command具体来说,命令

perl -p -e 'SOME_CODE_HERE;'

is exactly equivalent to running the following Perl program:完全等同于运行以下 Perl 程序:

LINE: while (<>) {
    SOME_CODE_HERE;
} continue {
    print or die "-p destination: $!\n";
}

Your regexp seems to be intended to match multiple lines at once, which obviously won't work if Perl is processing the input line by line.您的正则表达式似乎旨在一次匹配多行,如果 Perl 逐行处理输入,这显然不起作用。 To make it work as intended, you have (at least) two options:为了使其按预期工作,您(至少)有两个选择:

  1. Change Perl's notion of what constitutes a line by using the -0 NNN switch .通过使用-0 NNN开关来改变 Perl 关于什么构成行的概念。 In particular, the switch -0777 causes Perl to treat every input file as a single "line".特别是,开关-0777使 Perl 将每个输入文件视为单个“行”。

  2. Rewrite your code to eg use the .. flip-flop operator .重写您的代码,例如使用..触发器操作符

By the way, I strongly suspect that your regexp doesn't mean what you think it means.顺便说一句,我强烈怀疑你的正则表达式并不意味着你认为它的意思。 In particular, [^\\^]+ matches a string of one or more characters that doesn't contain a caret ( ^ ).特别是, [^\\^]+匹配一个或多个不包含插入符号 ( ^ ) 的字符的字符串。 Since your input doesn't seem likely to contain any carets, this seems essentially equivalent to (?s:.+) (or just .+ if you use the /s modifier ).由于您的输入似乎不太可能包含任何插入符号,因此这似乎基本上等同于(?s:.+) (或者,如果您使用/s修饰符,则只是.+ )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM