我正在尝试使用命令行perl替换多行文件中的文本。我正在使用Ubuntu Natty。
以下是我的文本文件(名为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
以下是我的perl命令:
perl -i -pe "s/(\[mysqld\][^\^]+)/\1\nsometext/g" test.txt
但是,不是替换文件中的所有文本,下面是我最终的结果:
[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
#
我在RegexBuddy中为Perl尝试了Regex,它匹配了文本文件中的所有内容,但由于某种原因,它在命令行上使用perl无效。
我很感激一些帮助。
提前致谢。
答案 0 :(得分:26)
您正在逐行阅读文件,因此只有第一行符合您的正则表达式。你想要做的事情 - 如果你真的想要删除大部分内容 - 是使用-0
选项来诋毁文件,例如: -0777
。这是行结束处理,777
只是一个惯例用作八进制数的数字,足以导致文件淤塞。
perl -0777 -i -pe 's/(\[mysqld\][^\^]+)/$1\nsometext/g' test.txt
另外,我更换了你的报价。如果你在* nix,你似乎是,单引号是更好的。例如,$1
不会被shell插入。
答案 1 :(得分:5)
-p
switch使Perl迭代输入的每个行并为每个行执行给定的代码(并在之后打印行)。具体来说,命令
perl -p -e 'SOME_CODE_HERE;'
完全等同于运行以下Perl程序:
LINE: while (<>) {
SOME_CODE_HERE;
} continue {
print or die "-p destination: $!\n";
}
你的regexp似乎是要同时匹配多行,如果Perl逐行处理输入,这显然是行不通的。为了使其按预期工作,您有(至少)两个选项:
使用-0NNN
switch更改Perl关于行的构成的概念。特别是,开关-0777
使Perl将每个输入文件视为单个“行”。
将您的代码重写为例如使用..
flip-flop operator。
顺便说一句,我强烈怀疑你的正则表达式并不意味着你的意思。特别是,[^\^]+
匹配一个不包含插入符号(^
)的一个或多个字符的字符串。由于您的输入似乎不太可能包含任何插入符号,因此如果您使用/s
modifier,这似乎基本等同于(?s:.+)
(或仅.+
。)