__line does not have a concept of replacing lines #186

Closed
opened 2021-11-20 15:21:00 +00:00 by ungleich-gitea · 4 comments

Created by: telmich

__line bla --regex '^mailman .*' --line mailman other stuff" does not replace the following line:

mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py

Because the current concept is that "anything that matches must be the right one"

Right? No. Yes? No?

*Created by: telmich* __line bla --regex '^mailman .*' --line mailman other stuff" does not replace the following line: mailman unix - n n - - pipe flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py Because the current concept is that "anything that matches must be the right one" Right? No. Yes? No?
ungleich-gitea added the
Stale
label 2021-11-20 15:21:00 +00:00
Author
Owner

closed

closed
Author
Owner

Created by: matthijskooijman

I guess things can be added to __line without breaking backward compatibility, but a new type is fine too. I don't really like __smart_line much, since it doesn't actually indicate what it can do, but perhaps a better name will present itself later.

Even for a new type, my above questions seem valid?

*Created by: matthijskooijman* I guess things can be added to `__line` without breaking backward compatibility, but a new type is fine too. I don't really like `__smart_line` much, since it doesn't actually indicate what it can do, but perhaps a better name will present itself later. Even for a new type, my above questions seem valid?
Author
Owner

Created by: telmich

@matthijskooijman I suggest to create a new type, let's call it __smart_line that is empty that we can reiterate on until satisfied. That way we don't orientate too much on the previous design of __line, which has been there since the very first days of cdist.

*Created by: telmich* @matthijskooijman I suggest to create a new type, let's call it __smart_line that is empty that we can reiterate on until satisfied. That way we don't orientate too much on the previous design of __line, which has been there since the very first days of cdist.
Author
Owner

Created by: matthijskooijman

I've also ran into this one, wanting to update a variable assignment in a file. e.g. I want to replace foo=.* with foo=bar. I want to implement this, but I'm not sure what the right approach is here, so comments are welcome.

I'm thinking of adding a --state=replace option (or something similar).

I can see a few variants:

  • The simplest case is to first remove any lines matching --regex, and then appending the --line. This works for simple containing a plain list of variable=value assignments. To check whether something needs to happen, the code should see if any line matches --regex (excluding lines exactly matching --line), or see if there is no line matching --line (note that it should probably not be required that --line matches the regex).

  • A more powerful variant is to remove the line matched by --regex and replace that line (in its original position) with --line. This also allows processing more complex file formats, where the line must be in a specific space (provided that a matching line is already there). One question is what to do when multiple lines match (I can imagine it could be useful to replace all occurences sometimes, while sometimes you only want the first or last), or what to do when no lines match (should the line still be appended?). One could also extend this to a more powerful generic search-replace (e.g. using a sed expression, with capturing etc.), but I suspect that might be better suited for a different type.

    Implementing this is more tricky. Cooking something up with sed seems obvious, but then the --regex semantics subtly change (IIRC sed and grep regexes are not exactly the same). Also, this needs proper escaping of the s/// replace argument, which is also non-trivial I think. awk has egrep-compatible regexes, but that's not exactly the same of course. One could perhaps use grep to report line numbers and then use sed or awk to process those?

A related thought: Having an --insert-after-regex option might be useful, to control where the line should be appended (regardless of replacement, this could be used to e.g. say --insert-after '^\[some_section\]$' to insert a line in the right section of a .ini file).

Any thoughts on this?

*Created by: matthijskooijman* I've also ran into this one, wanting to update a variable assignment in a file. e.g. I want to replace `foo=.*` with `foo=bar`. I want to implement this, but I'm not sure what the right approach is here, so comments are welcome. I'm thinking of adding a `--state=replace` option (or something similar). I can see a few variants: - The simplest case is to first remove any lines matching `--regex`, and then appending the `--line`. This works for simple containing a plain list of `variable=value` assignments. To check whether something needs to happen, the code should see if any line matches `--regex` (excluding lines exactly matching `--line`), or see if there is no line matching `--line` (note that it should probably not be required that `--line` matches the regex). - A more powerful variant is to remove the line matched by `--regex` and replace that line (in its original position) with `--line`. This also allows processing more complex file formats, where the line must be in a specific space (provided that a matching line is already there). One question is what to do when multiple lines match (I can imagine it could be useful to replace all occurences sometimes, while sometimes you only want the first or last), or what to do when no lines match (should the line still be appended?). One could also extend this to a more powerful generic search-replace (e.g. using a sed expression, with capturing etc.), but I suspect that might be better suited for a different type. Implementing this is more tricky. Cooking something up with `sed` seems obvious, but then the `--regex` semantics subtly change (IIRC `sed` and `grep` regexes are not exactly the same). Also, this needs proper escaping of the `s///` replace argument, which is also non-trivial I think. `awk` has `egrep`-compatible regexes, but that's not exactly the same of course. One could perhaps [use grep to report line numbers](https://stackoverflow.com/questions/6958841/use-grep-to-report-back-only-line-numbers) and then use `sed` or `awk` to process those? A related thought: Having an `--insert-after-regex` option might be useful, to control where the line should be appended (regardless of replacement, this could be used to e.g. say `--insert-after '^\[some_section\]$'` to insert a line in the right section of a .ini file). Any thoughts on this?
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: ungleich-public/cdist#186
No description provided.