How to preserve new line in shell script output? [duplicate] - bash

This question already has answers here:
Capturing multiple line output into a Bash variable
(7 answers)
Closed 5 years ago.
I have a line in my shell script like below
output_logs=`sh script2.sh $1 $2`
script2.sh produce lots of lines of logs. I want to grep specific lines of its output. The problem I have is $output_logs has the entire output of script2.sh as a single line string and grep produces strange results because of this. How to get the logs from script2.sh to be stored in individual lines?

Maybe you should try something like this.
output_logs=`sh script2.sh $1 $2`
echo "$output_logs"
Note that this is different from echo $output_logs.
The double-quoted version of the variable preserves internal spacing of the value exactly as it is represented in the variable — newlines, tabs, multiple blanks and all — whereas the unquoted version replaces each sequence of one or more blanks, tabs and newlines with a single space.

Related

Can I get the original quote characters surrounding arguments in my Bash script? [duplicate]

This question already has answers here:
How can I preserve quotes in printing a bash script's arguments
(7 answers)
Closed 4 years ago.
I have a script that logs the user argument list. This list is later processed by getopt.
If the script is started like:
./script.sh -a 'this is a sentence' -b 1
... and then I save "$#", I get:
-a this is a sentence -b 1
... without the single quotes. I think (because of the way Bash treats quotes) these are removed and are not available to the script.
For logging accuracy, I'd like to include the quotes too.
Can the original argument list be obtained without needing to quote-the-quotes?
No, there is no way to obtain the command line from before the shell performed whitespace tokenization, wildcard expansion, and quote removal on it.
If you want to pass in literal quotes, try
./script.sh '"-a"' '"this is a sentence"' '"-b"' '"1"'
Notice also how your original command line could have been written
'./script.sh' '-a' 'this is a sentence' '-b' '1'

Shell variable unexpected empty in if-then statement after calling sed [duplicate]

This question already has answers here:
How to pass the value of a variable to the standard input of a command?
(9 answers)
Closed 1 year ago.
I have a shell script:
TOPDIR=`pwd`
FOLDER=$($TOPDIR | sed 's/\//\_/g')
if [[ condition ]];then
source ~/[$FOLDER]-build/build-env.sh
fi
the TOPDIR here is /home/uname/project, so the variable FOLDER is supposed to be _home_uname_project because sed is called to replace / with _.
But it goes wrong when executing, terminal tells that /home/uname/[]-build/build-env.sh: No such file or directory which, I guess, means that FOLDER is unexpected empty in the if-then statement. Can anybody help me with figuring this out?
If you look at the output of just
$TOPDIR | sed 's/\//\_/g'
you'll realize that it's empty; it's trying to execute a command equal to the contents of $TOPDIR and pipe the output of that into sed, but there is no output in the first place.
You could do
pwd | sed 's\//_/g'
instead (no need to escape _), which would work.
Or, instead of using an external tool, you could use parameter expansion
topdir="$(pwd)"
topdir="${topdir//\//_}"
with the same result.
Notice that uppercase variable names are discouraged, as they're more likely to clash with existing, reserved names.

Nested quotes in bash -- passing single argument containing spaces [duplicate]

This question already has answers here:
How to substitute quoted, multi-word strings as arguments?
(4 answers)
Closed 7 years ago.
script.sh:
#!/bin/bash
echo "First argument: $1"
wrapper.sh:
#!/bin/bash
CALLER='./script.sh "this should be one argument"'
$CALLER
what happens:
$ ./wrapper.sh
First argument: "this
what I was expecting:
$ ./wrapper.sh
First argument: this should be one argument
I tried different exercises to make it work the way I want it, but I can't find the way to invoke script.sh with single argument containing spaces from within wrapper.sh.
I would also like to understand the way nested quotes are interpreted.
This works instead (only last line changed):
#!/bin/bash
CALLER='./script.sh "this should be one argument"'
eval "$CALLER"
The reason for this is that quoting is applied at a different place in the parsing process than variable substitution, so you need to re-run the result of the substitution ($CALLER) through the parsing process (using eval), but quoted (the "…" around $CALLER) to avoid the field splitting that comes with the substitution already.
Further reading: the POSIX documentation on this, and the links already given in comments.

echo that shell-escapes arguments [duplicate]

This question already has answers here:
Command to escape a string in bash
(5 answers)
Closed 4 years ago.
Is there a command that not just echos it's argument but also escapes them if needed (e.g. if a argument contains white space or a special character)?
I'd need it in some shell magic where instead of executing a command in one script I echo the command. This output gets piped to a python script that finally executes the commands in a more efficient manner (it loads the main() method of the actual target python script and executes it with the given arguments and an additional parameter by witch calculated data is cached between runs of main()).
Instead of that I could of course port all the shell magic to python where I wouldn't need to pipe anything.
With bash, the printf builtin has an additional format specifier %q, which prints the corresponding argument in a friendly way:
In addition to the standard printf(1) formats, %b causes printf to expand backslash escape sequences in the corresponding argument (except that \c terminates output, backslashes in \', \", and \? are not removed, and octal escapes beginning with \0 may contain up to four digits), and %q causes printf to output the corresponding argument in a format that can be reused as shell input.
So you can do something like this:
printf %q "$VARIABLE"
printf %q "$(my_command)"
to get the contents of a variable or a command's output in a format which is safe to pass in as input again (i.e. spaces escaped). For example:
$ printf "%q\n" "foo bar"
foo\ bar
(I added a newline just so it'll be pretty in an interactive shell.)

Bash loop - tokenize on lines rather than words [duplicate]

This question already has answers here:
Bash and filenames with spaces
(6 answers)
Closed 8 years ago.
I'm writing a script to do variable substitution into a Java properties file, of the format name=value. I have a source file, source.env like this:
TEST_ENV_1=test environment variable one
TEST_ENV_2=http://test.environment.com/one
#this is a comment with an equal sign=blah
TEST_ENV_3=/var/log/test/env/2.log
My script will replace every occurence of TEST_ENV_1 in the file dest.env with "test environment variable one", and so on.
I'm trying to process a line at a time, and having problems because looping on output from a command like sed or grep tokenizes on white space rather than the entire line:
$ for i in `sed '/^ *#/d;s/#.*//' source.env`; do
echo $i
done
TEST_ENV_1=test
environment
variable
one
TEST_ENV_2=http://test.environment.com/one
TEST_ENV_3=/var/log/test/env/2.log
How do I treat them as lines? What I want to be able to do is split each line apart on the "=" sign and make a sed script with a bunch of substitution regex's based on the source.env file.
sed '/^ *#/d;s/#.*//' source.env | while read LINE; do
echo "$LINE"
done
An alternative is to change $IFS as per #Jim's answer. It's better to avoid backticks in this case as they'll cause the entire file to be read in at once, whereas piping the output of sed to while above will allow the file to be processed line by line without reading the whole thing in to memory.

Resources