> 1. Find and replace a pattern in a codebase with capture groups
> git grep -l pattern | xargs gsed -ri 's|pat(tern)|\1s are birds|g'
Or, in IDEA, Ctrl-Shift-r, put "pat(tern)" in the first box and "$1s are birds" in the second box, Alt-a, boom. Infinitely easier to remember, and no chance of having to deal with any double escaping.Bash patterns I use weekly
31–40 of 115 posts
Re: Bash patterns I use weekly
#32> Use for to iterate over simple lists I definitely use this all the time. Also, generating the list of things over which to iterate using the output of a command: for thing in $(cat file_with_one_thing_per_line) ; do ...
xargs -n1 command Re: Bash patterns I use weekly
#33 grep -l -r pattern /path/to/files | while read x; do echo $x; done
or the like.This uses bash read to split the input line into words, then each word can be accessed in the loop with variable `$x`. Pipe friendly and doesn't use a subshell so no unexpected scoping issues. It also doesn't require futzing around with arrays or the like.
One place I do use bash for loops is when iterating over args, e.g. if you create a bash function:
function my_func() {
for arg; do
echo $arg
done
}
This'll take a list of arguments and echo each on a separate line. Useful if you need a function that does some operation against a list of files, for example.Also, bash expansions (https://www.gnu.org/software/bash/manual/html_node/Shell-Par...) can save you a ton of time for various common operations on variables.
Re: Bash patterns I use weekly
#34I have something like this in my bashrc: preexec () { # shellcheck disable=2034 _CMD_START="$(date +%s)" } trap 'preexec; trap - DEBUG' DEBUG PROMPT_COMMAND="_CMD_STOP=\$(date +%s) let _CMD_ELAPSED=_CMD_STOP-_CMD_START if [ \$_CMD_ELAPSED -gt 5 ]; then _TIME_STR=\" (\${_CMD_ELAPSED}s)\" else _TIME_STR='' fi; " PS1="\n\u@\h \w\$_TIME_STR\n\\$ " PROMPT_COMMAND+="trap 'preexec; trap - DEBUG' DEBUG" Whenever a command ta…
Re: Bash patterns I use weekly
#35> Use for to iterate over simple lists I definitely use this all the time. Also, generating the list of things over which to iterate using the output of a command: for thing in $(cat file_with_one_thing_per_line) ; do ...
Re: Bash patterns I use weekly
#36I've always had trouble getting `for` loops to work predictably, so my common loop pattern is this: grep -l -r pattern /path/to/files | while read x; do echo $x; done or the like. This uses bash read to split the input line into words, then each word can be accessed in the loop with variable `$x`. Pipe friendly and doesn't use a subshell so no unexpected scoping issues. It also doesn't require futzing around with arr…
The problem with the pipe-while-read pattern is that you can't modify variables in the loop, since it runs in a subshell.
Re: Bash patterns I use weekly
#37I've always had trouble getting `for` loops to work predictably, so my common loop pattern is this: grep -l -r pattern /path/to/files | while read x; do echo $x; done or the like. This uses bash read to split the input line into words, then each word can be accessed in the loop with variable `$x`. Pipe friendly and doesn't use a subshell so no unexpected scoping issues. It also doesn't require futzing around with arr…
Re: Bash patterns I use weekly
#38I've always had trouble getting `for` loops to work predictably, so my common loop pattern is this: grep -l -r pattern /path/to/files | while read x; do echo $x; done or the like. This uses bash read to split the input line into words, then each word can be accessed in the loop with variable `$x`. Pipe friendly and doesn't use a subshell so no unexpected scoping issues. It also doesn't require futzing around with arr…
> I've always had trouble getting `for` loops to work predictably, so my common loop pattern is this: The problem with the pipe-while-read pattern is that you can't modify variables in the loop, since it runs in a subshell.
Re: Bash patterns I use weekly
#39I want to like this, but the for loop is unnecessarily messy, and not correct. for route in foo bar baz do curl localhost:8080/$route done That's just begging go wonky. Should be stuff="foo bar baz" for route in $stuff; do echo curl localhost:8080/$route done Some might say that it's not absolutely necessary to abstract the array into a variable and that's true, but it sure does make edits a lot easier. And, the orig…
Even more correct would be to use an array: stuff=("foo foo" "bar" "baz") for route in "${stuff[@]}"; do curl localhost:8080/"$route" done
IFS=' ' read -ra routes Re: Bash patterns I use weekly
#40Earlier quoted context omitted.
> I've always had trouble getting `for` loops to work predictably, so my common loop pattern is this: The problem with the pipe-while-read pattern is that you can't modify variables in the loop, since it runs in a subshell.
It’s a trade off. I had to use a piped loop earlier this year to extract fallout new Vegas mods and textures since they all had spaces in their file names. For this it was perfect to pipe a list of the names to a loop, but for 99% of things I just use a for loop
BTW, the problem I mentioned earlier can be avoided by using `
$ x=1
$ seq 5 | while read n; do (( x++ )); done
$ echo $x
1
$ while read n; do (( x++ )); done
Almost makes me wonder what the benefit of preferring a pipe here is. I guess it's just about not having to specify what part of the pipeline is in the same shell.