greymd / teip

Masking tape to help commands "do one thing well"
MIT License
571 stars 19 forks source link

Occurrence option #27

Closed balupton closed 2 years ago

balupton commented 2 years ago

Would be great to be able to do this:

echo $'a\nb\nc\na\nb\nc' | teip -g '^b$' -o 2, -- '' | teip -g '^b$' -- sd '.*' 'B'

To get back:

a
B
c
a

c
greymd commented 2 years ago

Hi @balupton

Let me sort out a few things about your suggestion.

Please let me know if I misunderstand something.

Regarding 1), You can specify sd '.*' '' or something instead of '' as a workaround.

$ echo $'a\nb\nc\na\nb\nc' | teip -g '^b$' -- sd '.*' ''
a

c
a

c

However, I understand the desire to simplify the command. Since the behavior for empty argument is undefined, I will consider implementing this in the next version 👍

Regarding 2), Can you consider specifying the command teip -l 2- as a workaround? teip -l 2-

$ echo $'a\nb\nc\na\nb\nc' | teip -g '^b$' -- teip -l 2- -- sd '.' ''
a
b
c
a

c

The argument to teip can be teip itself. So you can call teip multiple times to refine the conditions more and more. 2- means "all fields after the second". Also, teip currently uses cut command compatible expressions, and does not expect 2,.

Currently, I think what you want to achieve can be done with the following.

$ echo $'a\nb\nc\na\nb\nc' | teip -g '^b$' -- teip -l 2- -- sd '.*' '' | teip -g '^b$' -- sd '.*' 'B'
a
B
c
a

c

If there is a case where your suggestion 2) would be more useful, feel free to let me know :)

balupton commented 2 years ago

I'm going to evaluate your suggestion today.

The use case is inside Dorothy's config-helper command, which updates configuration files, which currently I'm doing a gsed workaround:

https://github.com/bevry/dorothy/blob/f3ddf1b23c2dcdc98b501e5552663dd5f60f4b67/commands/config-helper#L215-L229

balupton commented 2 years ago

What's the best way to remove the extra occurrences from the output? Such that:

echo $'a\nb\nc\na\nb\nc' | teip -g '^b$' -- teip -l 2- -- printf '' | teip -g '^b$' -- printf 'B'

becomes:

a
B
c
a
c

I've tried several experiments but can't figure it out.

balupton commented 2 years ago

What's the best way to remove the extra occurrences from the output? Such that:

Okay, I came up with the following:

# ensure a trailing line, as otherwise the regexes get confused
content="$(cat "$file")"
content="${content%$'\n'}"$'\n'

# teip lacks the ability to delete lines,
# as such we have to replace lines we want to delete (the secondary occurences)
#   with a character sequence that wouldn't otherwise occur
# as such, we use \b\n as that is not a naturally occuring sequence
# this is then piped to sd which can delete lines
# then it is piped to sd again to perform the replacement of the first and intended occuerence
printf '%s' "$content" | \
    teip -g "$search_pattern" -- teip -l 2- -- sd '.*' $'\b\n' | \
    sd $'(\b\n)+' '' | \
    sd "$search_pattern" "$replace_pattern" \
    > "$file"
balupton commented 2 years ago

Closing, as figured it out with your suggestion. Thank you for all your help @greymd

For those interested, search for teip inside here for how I'm using it:

https://github.com/bevry/dorothy/blob/master/commands/config-helper