Preserving newlines when using curl in a bash script - bash

I'm currently writing a script that will ultimately parse some baseball player ID numbers from MLB's Gameday data. I have set up my script so far to input today's date into the URL and to accept a team name as a command line argument.
The next step is to pass the URL to curl to get a list of today's games and the find the appropriate one by using grep with the team name.
When I write this on the command line:
curl -s http://gd2.mlb.com/components/game/mlb/year_2017/month_05/day_20/ | grep tormlb
It works.
However, when I write this in my script:
mlb_dir=$(curl -s $url | grep $team)
echo $mlb_dir
I am returned a mess of HTML without any line breaks. $url is equivalent to the url in the code block above and $team is set to "tormlb" just like above.
I am confused how I can get the result I want when I use the command line but not when I run my script. Any clue where I am going wrong?

When you pass a variable to a command, the variable is expanded and then split into arguments by whitespace. echo then outputs its arguments separated by spaces.
To ensure the variable is treated as a single argument, wrap it in double quotes. You should also do this for the other variables you are using in your code.
mlb_dir=$(curl -s "$url" | grep "$team")
echo "$mlb_dir"
Further information: http://tldp.org/LDP/abs/html/quotingvar.html

Related

How to get Phpunit Test Summary

Im currently working on a Phpunit test and i was wondering if is it possible to get the Test Summary and store it to a variable so i can send it via Email?.
Time: 11.92 minutes, Memory: 20.00Mb
There were 4 failures:
1) BingTestTool::testPushCampaign_without_status
Failed asserting that two strings are equal.
--- Expected
+++ Actual
## ##
-''
+'Active'
Here is the result that phpunit outputs in the console, can i store this to a variable? so that i can send it tru email after the test run
If you run phpunit in your console then just pipe its output to mail:
$ phpunit | mail test#example.org -s 'Results of phpunit'
The -s command line argument allows setting the email's Subject.
If the execution of phpunit is just a step of a longer process (a deployment, for example) and you need the output for some processing, you can enclose the phpunit command into backquotes (``) or $() and use the expression as the right-hand side of an assignment:
RESULT="`phpunit`"
or
RESULT="$(phpunit)"
The double quotes around the expression are needed to keep the output (which is a multi-line string) as a single word and prevent the shell from interpreting it. There must be no spaces around the equal sign.
Now you can display it:
echo "$RESULT"
or pipe it to the input of various Unix programs. For example:
echo "$RESULT" | grep '^Time:' | cut -f1 -d,
feeds the content of variable $RESULT to grep that extracts and outputs only the line that starts with Time:; the output of grep is piped then to cut to keep only the first column using , as delimiter.

How to pass a shell script argument as a variable to be used when executing grep command

I have a file called fruit.txt which contains a list of fruit names (apple, banana.orange,kiwi etc). I want to create a script that allows me to pass an argument when calling the script i.e. script.sh orange which will then search the file fruit.txt for the variable (orange) using grep. I have the following script...
script name and argument as follows:
script.sh orange
script snippet as follows:
#!/bin/bash
nameFind=$1
echo `cat` "fruit.txt"|`grep` | $nameFind
But I get the grep info usage command and it seems that the script is awaiting some additional command etc. Advice greatly appreciated.
The piping syntax is incorrect there. You are piping the output of grep as input to the variable named nameFind. So when the grep command tries to execute it is only getting the contents of fruit.txt. Do this instead:
#!/bin/bash
nameFind=$1
grep "$nameFind" fruit.txt
Something like this should work:
#!/bin/bash
name="$1"
grep "$name" fruit.txt
There's no need to use cat and grep together; you can simply pass the name of the file as the third argument, after the pattern to be matched. If you want to match fixed strings (i.e. no regular expressions), you can also use the -F modifier:
grep -F "$name" fruit.txt

Unix Variable Declaration

Hello I'm a total beginner in shell scripting.
I have a log file named logA.log and a B.sh file.
In log file there are some lines and I want to find the number of a spesific word in that log (in last 10 line) by executing the B.sh
In B I wrote
#!/bin/bash
variableString = tail -10f /home/appuser/logA.log
grep ERROR $variableString | wc -l
but the output is:
variableString: command not found
I know "grep" line is working but I cannot reach the logA in b.sh.
How can I define a variable called variableString as last 10 line of logA
Your commands are ok but you have to be aware of the way to store command output: var=$(command). Also, you may get several lines, so quote the return command to keep the format. Hence, you should use:
variableString="$(tail -10f /home/appuser/logA.log)"
grep ERROR "$variableString" | wc -l
When you get the error
variableString: command not found
it is because as you define your syntax, bash interprets that has to execute the variableString command with the = tail -10f /home/appuser/logA.log parameters. See Basic bash script variable declaration - command not found for further information regarding this.
tail -f ("follow") will not finish, so it never gets to the next line. You probably meant tail -n 10 (the -n makes it POSIX compatible).
You cannot use spaces around equals signs when assigning a variable.
Variables are assigned to the string which the right-hand side evaluates to. Without special constructs, the result will simply be the literal string after the equals sign.
You should quote variables to avoid expansion.
In summary, you should use:
variableString=$(tail -10 /home/appuser/logA.log)

How to store output from a remote host in a variable bash script

I need to get all the wars on a remote tomcat server printed via my bash script.
I am able to ssh on the remote server and execute the command to get wars with version :-
${SSH} ${DEST_USER}#${DESTHOST} "Command"
however if I am storing it in a variable I don't get any-thing:-
output=${SSH} ${DEST_USER}#${DESTHOST} "Command"
echo $output
Based on a bit research if I try it as
output=$(${SSH} ${DEST_USER}#${DESTHOST} "Command"
echo $output
I got my output stored (need to understand why?).
Secondly the output I got in a single line as:
abc_1.2.war ijk_2.2.war hij_3.2.war xyx_5.1.war
how can I format this output some thing like:
Name version
abc 1.2
ijk 2.2
hij 3.2
xyz 5.1
Bash handles lines like this:
a=b c=d command
by temporarily setting environment variables "a" and "c" only for the duration of the command. They are not normal shell variables, and they won't exist after the command completes.
When you write
output=${SSH} ${DEST_USER}#${DESTHOST} "Command"
you are setting the "output" variable to the contents of "$SSH" for the duration of the "$DEST_USER#$DESTHOST" command (I'd expect you would receive a "command not found" error).
The way to capture the output of a command, as you have discovered, is with the $() syntax
output=$($SSH $DEST_USER#$DESTHOST "Command")
(Note you don't always have to put braces around your variable names, that's only strictly necessary when you need to separate the variable name from surrounding text)
For your text formatting question:
output="abc_1.2.war ijk_2.2.war hij_3.2.war xyx_5.1.war"
{
echo Name version
for word in $output; do # no quotes around $output here!
IFS=_ read name version <<< "$word"
echo "$name" "${version%.*}"
done
} | column -t
Name version
abc 1.2
ijk 2.2
hij 3.2
xyx 5.1
Here I use braces to group the header and the lines from the for-loop together to send them to column. I don't assume you know all the file extensions, but I do assume each file has an extension. The "${version%.*}" part removes the last dot and any following characters from the end of the value of the "version" variable.
Try echo "$output" (i.e. quotes).
I can't help with the 'why' right now. However you can produce the desired output from the variable(containing single line) as follows :
echo "Name version"
echo $output | grep -Eo "[a-zA-Z]+_[0-9]+.[0-9]+"| tr '_' ' '

How to execute lines of text on the clipboard as bash commands

I'm working with Mac OS X's pbpaste command, which returns the clipboard's contents. I'd like to create a shell script that executes each line returned by pbpaste as a separate bash command. For example, let's say that the clipboard's contents consists of the following lines of text:
echo 1234 >~/a.txt
echo 5678 >~/b.txt
I would like a shell script that executes each of those lines, creating the two files a.txt and b.txt in my home folder. After a fair amount of searching and trial and error, I've gotten to the point where I'm able to assign individual lines of text to a variable in a while loop with the following construct:
pbpaste | egrep -o [^$]+ | while read l; do echo $l; done
which sends the following to standard out, as expected:
echo 1234 >~/a.txt
echo 5678 >~/b.txt
Instead of simply echoing each line of text, I then try to execute them with the following construct:
pbpaste | egrep -o [^$]+ | while read l; do $l; done
I thought that this would execute each line (thus creating two text files a.txt and b.txt in my home folder). Instead, the first term (echo) seems to be interpreted as the command, and the remaining terms (nnnn >~/...) seem to get lumped together as if they were a single parameter, resulting in the following being sent to standard out without any files being created:
1234 >~/a.txt
5678 >~/b.txt
I would be grateful for any help in understanding why my construct isn't working and what changes might get it to work.
[…] the remaining terms (nnnn >~/...) seem to get lumped together as if they were a single parameter, […]
Not exactly. The line actually gets split on whitespace (or whatever $IFS specifies), but the problem is that the redirection operator > cannot be taken from a shell variable. For example, this snippet:
gt='>'
echo $gt foo.txt
will print > foo.txt, rather than printing a newline to foo.txt.
And you'll have similar problems with various other shell metacharacters, such as quotation marks.
What you need is the eval builtin, which takes a string, parses it as a shell command, and runs it:
pbpaste | egrep -o [^$]+ | while IFS= read -r LINE; do eval "$LINE"; done
(The IFS= and -r and the double-quotes around $LINE are all to prevent any other processing besides the processing performed by eval, so that e.g. whitespace inside quotation marks will be preserved.)
Another possibility, depending on the details of what you need, is simply to pipe the commands into a new instance of Bash:
pbpaste | egrep -o [^$]+ | bash
Edited to add: For that matter, it occurs to me that you can pass everything to eval in a single batch; just as you can (per your comment) write pbpaste | bash, you can also write eval "$(pbpaste)". That will support multiline while-loops and so on, while still running in the current shell (useful if you want it to be able to reference shell parameters, to set environment variables, etc., etc.).

Resources