[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#28056: Substitution doing global when it should not.
From: |
Assaf Gordon |
Subject: |
bug#28056: Substitution doing global when it should not. |
Date: |
Sat, 12 Aug 2017 19:51:57 -0600 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 |
Hello,
On 12/08/17 12:02 PM, Techwolf Lupindo wrote:
> A followup. I tried the command you hinted at. The result was the first
> match and substitution was done, but the rest of the file was deleted. This
> is using sed -i -e.
If you want to operate on just the first matching line, you can use
the following sed method:
printf "%s\n" a b c d a b c d | sed '/b/ { s/b/X/ ; :Y ; n ; bY }'
The sed program does the following:
/b/ - match *any* line that contains 'b'
{ ... } - sed commands grouped together, will be executed
when the current line matches 'b'
s/b/X/ - replace the first occurrence of 'b' with 'X' .
:Y - a label called 'Y' (arbitrary name)
n - read the next line and print it
bY - jump (=branch) to label Y
Effectively, the first time a line contains 'b'
matches the regex, sed will perform one replacement,
and then enter an endless loop of reading/printing the lines,
without executing any other sed commands (and thus,
not matching other 'b' lines and not performing replacements).
Expanding Eric's suggestion, your sed command might look like:
sed -e '/COMMAND ${MERCURIAL}/ { s::COMMAND ${MERCURIAL} -- cwd
${CMAKE_SOURCE_DIR}: ; :Y ; n; bY }'
Also,
When experimenting with sed commands, I'd recommend not using "-i"
(in-place replacements) - this could lead to data loss if your sed
command isn't working as expected, and you don't have a backup.
Lastly,
For quick-and-dirty manual sed replacements of single lines, you can
find the exact line number and replace just it.
Example:
$ wget https://hg....file/9d58c58cca90/indra/cmake/BuildVersion.cmake
$ grep -n 'COMMAND ${MERCURIAL}' BuildVersion.cmake
28: #COMMAND ${MERCURIAL} log -r tip:0 --template '\\n'
31: COMMAND ${MERCURIAL} identify -n
And then assuming you want to change only line 28, use a specific
and even shorter sed command:
sed '28s/}/} --cwd ${CMAKE_SOURCE_DIR} /' BuildVersion.cmake
The '28s/.../.../' tells sed to perform the 's' command only on line 28.
Hope this helps,
regards,
- assaf