]> git.nbdom.net Git - nb.git/commitdiff
bin/shell-replace
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Sat, 10 Dec 2022 17:03:08 +0000 (18:03 +0100)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Sat, 10 Dec 2022 17:03:08 +0000 (18:03 +0100)
bin/shell-replace [new file with mode: 0755]

diff --git a/bin/shell-replace b/bin/shell-replace
new file mode 100755 (executable)
index 0000000..c2a76a6
--- /dev/null
@@ -0,0 +1,313 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+#################################################################################
+#
+# VERSION
+#
+#################################################################################
+my $VERSION = '0.0.1';
+# NB 10.12.22
+# - create script
+
+#################################################################################
+#
+# GLOBALS
+#
+#################################################################################
+my ($NAME) = $0 =~ m,([^/]+)$,;
+
+# To ignore myself
+my $SHELL_IGNORE = '^my \$SHELL_IGNORE';
+
+#################################################################################
+#
+# ARGS
+#
+#################################################################################
+my $VERBOSE = $main::VERBOSE = 1;
+my $DEBUG = $main::DEBUG = 0;
+
+my %Opt = (
+);
+get_options(\%Opt);
+#help() unless @ARGV;
+$main::_DATA_ = undef;
+
+#################################################################################
+#
+# BEGIN
+#
+#################################################################################
+use Data::Dumper;
+use File::Find;
+if (!@ARGV and !-t STDIN) {
+       die "$NAME: option require file/path as arguments!\n" if $Opt{find};
+       @ARGV = "-";
+}
+
+
+#
+# Option --find
+#
+my @WANTED_FILES = ();
+if ($Opt{find}) {
+       File::Find::find({
+               wanted => \&wanted,
+               follow => 1,
+               follow_skip => 2,
+               no_chdir => 1
+       }, @ARGV);
+       #exit;
+       #die Dumper(\@WANTED_FILES);
+       @ARGV = @WANTED_FILES;
+}
+
+#
+# Process
+#
+my $hfile;
+my $file;
+
+for $file (@ARGV) {
+
+       if ($file eq "-") {
+               $hfile = <>;
+               $hfile = \*ARGV;
+       } else {
+               next if myself($file);
+               open($hfile,"<",$file);
+       }
+
+       verbose(1,">Processing: $file\n");
+
+       my @lines = &shell_replace($hfile);
+       print map { $_ } @lines;
+       close $hfile;
+}
+
+#################################################################################
+#
+# END
+#
+#################################################################################
+exit 0;
+
+#################################################################################
+#
+# Functions
+#
+#################################################################################
+sub verbose {
+       my $level = shift @_;
+       return 0 if $VERBOSE <= $level;
+       print STDERR join(" ",@_)."\n";
+}
+sub myself {
+       my $file = shift @_;
+       if ($file eq $0 or $file =~ /(^|\/)$NAME$/) {
+               verbose(1,"ignore file $file\n");
+               return 1
+       }
+       return 0;
+}
+
+sub wanted {
+       my $file = $File::Find::name;
+
+       # Dont want the myself
+       return if myself($file);
+
+       my $hfile;
+       open($hfile,"<","$file");
+       while (<$hfile>) {
+               # Dont want the myself
+               next if /$SHELL_IGNORE/;
+
+               next unless /^.{1,3}<SHELL_REPLACE/;
+
+               verbose(1,">Found: $file\n");
+               push @WANTED_FILES, $file;
+               last;
+       }
+       close $hfile;
+}
+
+sub shell_replace {
+my $ident;
+my $i;
+my $change;
+my $cmd;
+my @lines = ();
+
+my $hfile = shift @_;
+       while (my $line = <$hfile>) {
+
+               if (
+                       $line =~ /^(\s*).{1,3}>SHELL_REPLACE (.*)$/
+                       ..
+                       $line =~ /^\s*.{1,3}<SHELL_REPLACE.*/
+               ) {
+
+                $change = 1;
+                $ident = $1 ? $1 : "";
+                #die $line unless $2;
+                #warn ">>".$line; next;
+                $i++;
+                if ($2) {
+                        $cmd = "bash -lc \"$2\"";
+                        if ($i==1) { push @lines, $line; push @lines, map{s/^/$ident/;$_} `$cmd`; }
+                        elsif (/^\s*.{1,3}<SHELL_REPLACE/) { push @lines, $line; }
+                }
+
+               } elsif ($line =~ /^(\s*).{1,3}=SHELL_REPLACE (.*)$/) {
+                       $ident = $1;
+                       <>;
+                       push @lines, $line;
+                       push @lines, map{ s/^/$ident/; $_ } `$cmd`;
+                       $change = 1;
+
+               } else {
+                       $i=0;
+                       push @lines, $line;
+
+               }
+
+       }
+       return @lines;
+}
+
+sub help {
+#------------------------------------------------------------------------------
+# Print help and exit
+#------------------------------------------------------------------------------
+
+       require 'Pod/Usage.pm' unless $INC{'Pod/Usage.pm'};
+
+       # Substitutions
+       sub pod_env {
+               my $v = '';
+               eval '$v = ref(\\'.$_[0].') eq "ARRAY" ? join(" ",'.$_[0].') : '.$_[0].'; return defined $v ? $v : qq|UNDEF|;';
+               return $v;
+       }
+
+       $main::_DATA_ =~ s/([@\$][A-Z_a-z\{\}]+)/pod_env($1)/eg;
+
+       my $in;
+       open($in,'<',\$main::_DATA_);
+
+       open(STDOUT,"|perl -pe 's/\.$$//g'".(($ENV{PAGER}||'') eq 'less' ? "|less -FRi" : ""));
+       my $opts = {
+               -input => $in,
+               -ouput => \*STDOUT,
+               -exitval => 'noexit',
+               -sections => [qw(SYNOPSIS DESCRIPTION OPTIONS)],
+               -verbose => ($Opt{'help'} ? 99 : 3),
+       };
+
+       Pod::Usage::pod2usage($opts);
+       close $in;
+       close STDOUT;
+
+       exit 0;
+}
+
+#------------------------------------------------------------------------------
+# Print version and exit
+#------------------------------------------------------------------------------
+sub version { print "$NAME: version [$VERSION]\n"; exit 0; }
+
+#------------------------------------------------------------------------------
+# Get options from pod
+#------------------------------------------------------------------------------
+sub get_options {
+
+       use Getopt::Long qw(:config no_ignore_case no_auto_abbrev);
+
+       my @Opt;
+
+       sub pod_opt {
+               local $_;
+               my $o = shift;
+               $o =~ s/(=.|[\+\-\!]$)//;
+               $o = join(", ",map{"-$_"} split(/[\|,:;]/,$o));
+               return "$o";
+       }
+
+       while (<DATA>) {
+               s/option\[([^\]]+)\]/push(@Opt,$1) and pod_opt($1)/eg;
+               $main::_DATA_ .= $_;
+       }
+
+       GetOptions($_[0],@Opt) || exit -1;
+
+       help() if $_[0]{'help'} or $_[0]{'man'};
+       version() if $_[0]{'version'};
+
+       $main::VERBOSE = $VERBOSE = $_[0]{'verbose'} if defined $_[0]{'verbose'};
+       $main::DEBUG = $DEBUG = $_[0]{'debug'} if defined $_[0]{'debug'};
+
+}
+
+__DATA__
+
+=head1 NAME
+
+$NAME - Script replace tags with command in text files
+
+=head1 SYNOPSIS
+
+$NAME path/file.txt
+$NAME --find path/
+
+=over
+
+=item $NAME --verbose
+
+=item $NAME --help
+
+=back
+
+=head1 DESCRIPTION
+
+Find files which contains start and tags >SHELL_REPLACE .. <SHELL_REPLACE.
+Execute the command aflter the start tag and replace the lines until the end tag.
+Example of file content:
+#>SHELL_REPLACE dbq.php nb meta ls key,val cat=mime.comment format=vim_hash preff=$'\t' name=mimeComment
+.....
+#<SHELL_REPLACE
+
+Description!
+
+=head1 OPTIONS
+
+ -option[find|f!]      Search first files containing tags from args
+ -option[verbose|v+]   Verbose mode: increase the verbosity level.
+ -option[debug+]         Debug mode: increase the verbosity level.
+ -option[version|V]   Print version (default: $VERSION)
+ -option[help|h|?]  Print a brief help message and exits.
+ -option[man]           Print the manual page and exits.
+
+=cut
+
+=head1 REQUIRES
+
+Getopt::Std, Pod::Usage
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2022 Nicolas Boisselier
+
+This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+See <http://www.gnu.org/licenses/>.
+
+=head1 SEE ALSO
+
+perl(1), http://perldoc.perl.org/perlpodstyle.html
+
+=head1 AUTHOR
+
+Nicolas Boisselier <nico@nbdom.net>
+
+=cut