patternbashgitMinor
Git pie - Perl oneliner for Git
Viewed 0 times
perlforgitpieoneliner
Problem
I often make changes on my code-base and manually using
Furthermore, because I am working on Cygwin, I cannot do real in-place replacement without a temporary file that I have to manually suppress afterwards.
Last but not least,
I am sure some simplifications can be made on this piece of code, so I ask for your opinion.
The usage is:
I decided to slurp the whole file in memory in order to do multiline regexes which is very convenient sometime despite the performance.
There is perhaps a missing feature: the ability to exclude or include some file extensions only or simply allow this call:
I still didn't figure out how I want to do it. One possible way is:
```
$ git pie 's/foo/b
sed, awk or perl -pi -e is not always as efficient as having a simple alias: git pie. Furthermore, because I am working on Cygwin, I cannot do real in-place replacement without a temporary file that I have to manually suppress afterwards.
Last but not least,
sed, awk and perl -pi -e touch all the files that make them new from the point of view of make. I rather want to touch only the file with real changes so I wrote this Git alias:[alias]
# Replace
pie = "!f() { \
git ls-files -z | xargs -0 perl -e ' \
my $eval = shift @ARGV; \
foreach my $file (@ARGV) { \
next unless -f $file; \
open my $fd, \"}; \
close $fd; \
my $new = do { $_ = $content; eval $eval; }; \
if ($content ne $new) { \
open my $fd, \">\", $file; \
print $fd $_; \
close $fd; \
} \
} \
' \"$1\"; }; f"I am sure some simplifications can be made on this piece of code, so I ask for your opinion.
The usage is:
$ git pie s/foo/bar/gI decided to slurp the whole file in memory in order to do multiline regexes which is very convenient sometime despite the performance.
There is perhaps a missing feature: the ability to exclude or include some file extensions only or simply allow this call:
$ git ls-files | grep -P '[.][ch]
I still didn't figure out how I want to do it. One possible way is:
```
$ git pie 's/foo/b | xargs git pie s/foo/bar/I still didn't figure out how I want to do it. One possible way is:
```
$ git pie 's/foo/b
Solution
As written,
You can inject
While
Perl has a mechanism to read whole files specified on command-line and you can shorten your script further by employing it.
Tying all this together, your one-liner can fit in one line with some whitespace to spare. In 128 columns (plus four spaces of indent):
$new will contain the return value of s///, which is 1 (true) or the empty string (false). This will (almost) never match $content and you'll be rewriting every file unconditionally.You can inject
$1 directly without the pass-and-eval. This will stop the Perl script altogether in the event of an error, which is probably desirable.While
my and lexical open etc. are good habits, they're at odds with the design constraints of a one-liner that needs to survive multiple levels of quoting. For example, print FD prints $_ to handle FD, while print $fd needs an explicit $_ argument, else it prints the string representation of that handle to stdout. Just switching to a bareword-open saves you five characters.Perl has a mechanism to read whole files specified on command-line and you can shorten your script further by employing it.
Tying all this together, your one-liner can fit in one line with some whitespace to spare. In 128 columns (plus four spaces of indent):
[alias]
pie = "!f(){ git ls-files -z | xargs -0 perl -0777ne'$old=$_; '\"$1\"'; $_ ne $old and open FD, q|>|, $ARGV and print FD';} ;f"Code Snippets
[alias]
pie = "!f(){ git ls-files -z | xargs -0 perl -0777ne'$old=$_; '\"$1\"'; $_ ne $old and open FD, q|>|, $ARGV and print FD';} ;f"Context
StackExchange Code Review Q#158977, answer score: 4
Revisions (0)
No revisions yet.