简体   繁体   中英

How do I append text to the line containing a substitution in Perl?

My goal is to replace all named constants in a *.bas file with their corresponding values, then append a comment to the line with the value-constant pair for future reference.

For example, I want to change this line:

Print #lngFile, rst.GetString(adClipString, -1, ",", vbNullString);

To this:

Print #lngFile, rst.GetString(2, -1, ",", vbNullStrings); '2=adClipString

Where the ADODB constant adClipString is replaced with its long value 2 , and a comment is appended to the line.

The closest I've gotten is the following:

perl -pi -e 's/adClipString(.+\n)/2$1\x272=adClipString\n/' -- somefile.bas

...but I can't figure out how to exclude the \n from the capturing group without also overwriting every line in the file. As written, the comment is placed on a new line (which is not what I want). I'm sure the answer is right in front of me.

I'm new to perl, having only run it on the command line. I'm sure there is a better [read: working] way to approach this.

. doesn't match newlines, and perl -p processes one line at a time, so the string to replace never contains more than one line, and you don't need to match the newline character at all.

perl -pi -e 's/\badClipString\b(.*)/2$1\x272=adClipString/' -- somefile.bas

I changed .+ to .* because you didn't give any indication that adClipString shouldn't be matched at the end of a line. I also surrounded the word to replace with \b so that things like thisIsABadClipStringOtherVariable won't get replaced.

The added complication is that you have a file with Windows line endings: CR+LF. . doesn't match LF (line feed, the Unix/POSIX/basically-everyone-but-Windows-nowadays newline character) but it does match CR (carriage return). So this replacement puts a CR in the middle of the line (just before the comment start), which may confuse Windows programs. One way to fix this is to exclude the CR from the “rest of line” group.

perl -pi -e 's/\badClipString\b([^\r\n]*)/2$1\x272=adClipString/' -- somefile.bas

Another way to do this transformation would be to treat the string replacement and adding a comment as separate operations. An s command is considered true only if it makes a replacement.

perl -pi -e 's/\badClipString\b/2/ and s/\r?$/\x272=adClipString$&/' -- somefile.bas

Or, in a less one-liner-y but more readable way:

perl -pi -e 'if (s/\badClipString\b/2/) { s/\r?$/\x272=adClipString$&/ }' -- somefile.bas

The regex \r?$ matches at the end of a line, with an optional CR. The substitution puts additional text at the end of a line, with $& (which stands for the whole string matched by the regex) at the end to preserve the optional CR.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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