chmln / sd

Intuitive find & replace CLI (sed alternative)
MIT License
5.72k stars 136 forks source link

Is this possible? #285

Open elkarouh opened 9 months ago

elkarouh commented 9 months ago

I have a line line=Note AAA: BBB: CCC: I want to replace the ':' in all lines starting with Note with the character Z This would make the 'sd : Z' conditional on the presence of 'Note' Is this possible with sd ? In sed, i would do" sed '/^Note/s/:/Z/g' myfile

Many thanks

nc7s commented 8 months ago

Side note: you can surround any lines of code or otherwise preformatted content with a pair of ``` lines. See (GitHub Flavored) Markdown.

And yes, you can do that:

❯ printf 'Note AAA:\nBBB:\nCCC:\n' | sd '^Note(.*):' 'Note${1}Z'
Note AAAZ
BBB:
CCC:

This is kinda awkward if you are used to sed syntax, but otherwise just plain old regular expression.

elkarouh commented 8 months ago

This is not what I want to achieve. All occurrences of ':' should be replaced by Z In your solution, only the first occurrence is replaced.

nc7s commented 8 months ago

I want to replace the ':' in all lines starting with Note with the character Z This would make the 'sd : Z' conditional on the presence of 'Note' Is this possible with sd ? In sed, i would do sed '/^Note/s/:/Z/g' myfile

All occurrences of ':' should be replaced by Z In your solution, only the first occurrence is replaced.

I don't quite follow.

elkarouh commented 8 months ago

The result I want to get is 'Note AAA: BBB: CCC:' should become 'Note AAAZ BBBZ CCCZ' This is easy to achieve with sed. I seek a solution using sd

nc7s commented 8 months ago

Alright, I misunderstood ("over-interpreted" if you would) the single line example to be multiple lines misrepresented, due to the words "all lines".

As I now understand it, you want the replacement to happen iff a predicate is true. This as a general case is not possible with plain regexes (how sd currently operates). In a plain regex, after the "predicate" ^Note, you can only match a group (?:(?<span>[^:]*)?:) and replace them with ${span}Z. They can't arbitrarily stack up (not to mention the inability to express them in substitution), and a * after that group matches A: B: C: as a whole.

This is trivially solved with a little scripting if you are open to that.

If deemed necessary for sd, this probably needs a semantics along the lines of sd --line-by-line --predicate PREDICATE FIND REPLACE_WITH. Kinda verbose compared to sed, OTOH, sed syntax has been seen as cryptic. Can be implemented after https://github.com/chmln/sd/pull/287.

I'd suggest changing the title to something like "Predicated replacements".