Get variables replaced when I am a cat file

Is it possible that in a clean way to get the values ​​of variables when I cat, instead of variable names as indicated in the file. It's hard to explain, but here comes a simple example:

$ cat <<EOF $HOME EOF /home/myself 

cat returns / home / itself because it is already extended by the shell.

 $ echo \$HOME >/tmp/home $ cat /tmp/home $HOME 

cat just reads the file, I want $ HOME to expand here somehow with cat, because the file will contain variable names (not like HOME = / home / myself)

My question is that this is possible, otherwise I will have to write dirty code.

EDIT: These are large xml files containing

 <checkbox active="$value"> 

true or false

+3
source share
3 answers

It would be trivial to try in Python and see if this works for you. You can use the re.sub function to replace all occurrences of some pattern like "\$\w+" by calling the function that performs the conversion (and not to replace it). And for the replacement function, you can use os.getenv() , which, of course, takes the name of the variable and returns its value.

Edit: here is a full Python script that does the following:

 #!/usr/bin/python import fileinput import os import re def transform(match): return os.getenv(match.group(1)) # replace the "capture" to omit $ for line in fileinput.input(): # reads from stdin or from a file in argv print re.sub('\$(\w+)', transform, line), # comma to omit newline 
+2
source

cat copies its inputs intact to its outputs - at least in its original (1st Edition UNIX) form. He had no options to start. Then BSD added a bunch, and the original UNIX command objected: " cat returned from Berkeley flags" (see: 1 - passim). It should not be used to edit files, which is not its purpose. (I found a link to an article in the BSD (Mac OS X) man page for cat : Rob Pike, "UNIX Style, or cat -v Considered Malicious," USENIX Summer Conference Proceedings, 1983. See Also http: // quotes. cat-v.org/programming/ )

So, for the job you need something other than cat . I would recommend Perl or Python; Or you can do it quite easily. As an alternative, consider sed or perhaps awk .

 #!/usr/bin/env perl use strict; use warnings; while (<>) { foreach my $key (keys %ENV) { s/\$$key\b/$ENV{$key}/g; # $envvar s/\${$key}/$ENV{$key}/g; # ${envvar} } print; } 

This goes through the input line, looking for each environment variable in turn. An alternative mechanism is the search for possible variables and the corresponding replacement. This turns out to be a bit complicated, but doable:

 #!/usr/bin/env perl use strict; use warnings; while (<>) { while (m/\$((\w+))/ || m/\$({(\w+)})/) { my $key = $2; my $var = $1; s/\$$var/$ENV{$key}/g if defined $ENV{$key}; } print; } 

When I included the $ literal in captures, the replace operation did not work correctly.

+1
source

The obvious way to do this has many problems:

  # This will fail with certain inputs.  HTML will certainly be a problem
 # as the '<' and '>' characters will be interpreted as file redirects
 $ while read r;  do eval echo $ r;  done <input

The following perl class should correctly handle the problem for simple inputs.

  $ perl -pwe 'while (($ k, $ v) = each% ENV) {s / \ $ {? $ k}? / $ v /}' input

But it does nothing with constructs like $ {FOO-bar}. If you need to handle such constructions, it may be enough to avoid all shell metacharacters and execute a while / read loop:

  $ sed -e 's / \ ([<> & | ();] \) / \\\ 1 / g' input |  while read -rl;  do eval echo "$ l";  done

Please note that this is not reliable and safe. Consider what happens when you type, for example:

  \;  rm -rf /

I said "consider." Do not check this. Sed will insert a backslash before the semicolon, then eval will get the string "\\;" which will be interpreted as a single backslash followed by a semicolon, which includes an echo, and rm -rf is executed. Given the uncertainty of avoiding unknown input, it would probably be safer to stick with something like perl and explicitly replace the required sh-constructs. Sort of:

  $ perl -pwe 'while (($ k, $ v) = each% ENV) {s / \ $ {? $ k}? / $ v /}; 
     s / \ $ {[^ -] * - ([^}] *)} / $ 1 / g 'input

This has problems with input like $ {FOO = some-text}. To reliably get all sh constructions ($ {word: rhs}, where ":" can be any of "-", "?", "=", "+", "%", "#" Or any of them with by adding a colon (or a lot of other characters if you allow non-visit syntax)!) you will need to build a rather complicated set of comparisons.

+1
source

Source: https://habr.com/ru/post/887945/


All Articles