vincentaxhe has asked for the wisdom of the Perl Monks concerning the following question:

I have a shell script like this
declare -x KBD_DEV="/dev/input/$event" KBDCFG=$(envsubst < /home/vincent/.config/kmonad/$config) kmonad <(echo "$KBDCFG") &
It's for kmonad to run config when new event found, config have to contain variable like this
input (device-file "$KBD_DEV")
now I want to write it with perl, Is there an elegant way to do the same work of 'envsubst' and <(...) process substitution of shell, no need to use temp file and edit file.

Replies are listed 'Best First'.
Re: how perl do 'envsubst'
by NERDVANA (Priest) on Jul 01, 2024 at 04:46 UTC
    use autodie; use Path::Tiny; # read the file my $tpl= path("/home/vincent/.config/kmonad/$config")->slurp; # perform envsubst $tpl =~ s/\$ (?| (\w+) | \{(\w+)\} )/$ENV{$1}/gx; # open a pipe to a child process "kmonad" telling it to read from STDI +N open(my $fh, "|-", "kmonad", "/dev/fd/0"); # Write the template to kmonad's stdin $fh->print($tpl); $fh->close;

    If you also need to capture the output of kmonad, you'll need IPC::Open3, or IPC::Run.

    If you're trying to avoid CPAN modules, you can replace Path::Tiny with my $tpl= do { local $/= undef; open my $fh, "<", "/home/vincent/.config/kmonad/$config"; <$fh> }; which is less elegant and doesn't check for disk errors mid-read.

    Also... this is a very simple regex for replacing variables in the template. If your template is using fancy bash notations like ${FOO:-default} in the template then you probably need to shell out to bash for the envsubst.

    If you are OK with moving your whole template into the perl script itself, then just do like LanX suggested, or use a  <<END-style here-doc.

      thanks for your answer, I didn't know Path::Tiny do the work as File::Slurp, and $fh->print is same as print $fh, I have finished the script, all works great, the process substitution of shell is pipe to /dev/fd/ in essence

        Yep, you can see it in action with
        $ echo <(echo foo) /dev/fd/63
        But, now I just realized there is still a mystery!
        $ ls /dev/fd 0 1 2 3
        So... how can a program open /dev/fd/63 if it doesn't exist?
Re: how perl do 'envsubst'
by LanX (Saint) on Jun 30, 2024 at 15:40 UTC
    I don't know what envsubst does and why you need it. Please explain.

    Anyway you can set environment variables inside the %ENV hash, and all subprocesses will inherit them.

    If your real problem is to parse your config file, please show us its format.

    I once published a hack to read the ENV of a subprocess, it's listed in my home node, but I'm not sure if that's what you need.

    Update

    Sigh, envsubst seems to be a template system based on variable interpolation.

    This should do the trick already

    my $KBDCFG = qq~ input (device-file "$KBD_DEV") ~

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery