sd icon indicating copy to clipboard operation
sd copied to clipboard

Feature: Multiple find-replace expressions without pipe chaining

Open zachriggle opened this issue 4 years ago • 4 comments

One of the benefits of sed is that it allows multiple expressions to be chained in the same invocation of the binary. It appears that sd lacks this feature, which would make it even more versatile.

Feature Suggestion

By default, sd uses the first and second argument as find and replace_with and all other arguments are treated as files.

I suggest adding some additional mode of operation for suggesting multiple find and replace-with pairs. I'm not sure the best way to achieve this, but borrowing from sed to provide an e.g. -e flag to specify "the next two arguments are an additional find and replace-with" (which would be optional for the first two arguments to maintain the current mode of operation).

Examples

sed example

$ cat test
The quick brown fox jumps over the lazy dog

$  sed -E -e 's|quick|slow|' -e 's|dog|cat|' < test
The slow brown fox jumps over the lazy cat

sd example

It does not appear that this is possible with sd as additional arguments are interpreted as filenames, and the contents of the file(s) are replaced with the singular expression provided to sd.

What doesn't work

$ sd quick slow < test
The slow brown fox jumps over the lazy dog

$ sd quick slow dog cat < test
Error processing dog: No such file or directory (os error 2)
Error processing cat: No such file or directory (os error 2)

It would be nice to be able to specify additional patterns to sd. One can certainly use shell pipelining of multiple instances of sd to achieve this, but this breaks some of the other features -- namely the ability to perform in-place file modification. Pipelining also prevents modification of in-place files, as the file cannot be overwritten while it is opened earlier in the pipeline.

$ cat test
The quick brown fox jumps over the lazy dog

$ sd quick slow < test | sd dog cat >! test

$ cat test
<nil>

What works

What DOES work to achieve this feature is simply to invoke sd multiple times. However, this seems like it will cost a lot of overhead, since the entire file must be re-read on each invocation, which can be expensive depending on the size of the file.

$ cat test
The quick brown fox jumps over the lazy dog

$ sd quick slow test

$ sd cat dog test

$ cat test
The slow brown fox jumps over the lazy dog

It's also likely possible to do this with capture groups, but I can't think of a straightforward way to do this. Simply being able to specify additional find and replace-with, but this seems tedious and complex to maintain, which seems antithetical to the goal of sd.

zachriggle avatar Jul 20 '21 00:07 zachriggle

Such a feature would be welcome, and, I imagine, also more efficient, since there would need to be less copying memory around processes.

golddranks avatar Feb 08 '22 03:02 golddranks

1+

Anangaya avatar Feb 16 '23 13:02 Anangaya

I'd like to work on this

oriongonza avatar Oct 17 '23 15:10 oriongonza

@dev-ardi Sure! I've gone ahead and assigned you. Feel free to open a draft PR or ping me here if you have any questions

I'm not sure about the best way to express this feature through the CLI yet. Ideally sd could just take multiple pairs, but that conflicts with how sd reads file paths. I'm certainly open to ideas here

CosmicHorrorDev avatar Oct 17 '23 17:10 CosmicHorrorDev