Bash Function help, Empty output - linux

I'm trying to write this function that searches for vowels in string
x="A\|E\|I\|O\|U\|a\|e\|i\|o\|u"
string () {
if echo $1 | grep -q $x
then
echo $1 | tr -d $x
fi
}
string
When i run it, it returns empty string
I have tried to recreate this with out function and it worked
x="A\|E\|I\|O\|U\|a\|e\|i\|o\|u"
if echo $1 | grep -q $x
then
echo $1 | tr -d $x
fi
No function:
root#ubuntu-2gb-fra1-01:~# bash test2.sh "This website is for losers LOL!"
Ths wbst s fr lsrs LL!
With function:
root#ubuntu-2gb-fra1-01:~# bash test.sh "This website is for losers LOL!"
root#ubuntu-2gb-fra1-01:~#
Can anyone explain to me what's the reason?
Thanks

You run your function string without parameters. Hence inside string $1 is always empty and the condition is never met.
You can for instance call it as
string "$1"
to forward the current first argument to your function.

You need to add following line at the beginning of your code:
i=$1
and change the reference of variable in function from $1 to $i.

You don't need grep or tr for this.
string () {
case $1 in
*[AEIOUaeiou]*)
echo "${1//[AEIOUaeiou]/}";;
*) echo "$1";;
esac
}
But of course, the substitution does nothing if the string doesn't contain any of those characters, so all of this can be reduced to
string () {
echo "${1//[AEIOUaeiou]/}"
}
The case statement is portable all the way back to the original Bourne shell, but the ${variable//pattern/replacement} syntax is specific to Bash.
Call it like string "$1" to run it on the script's first command-line argument.

Related

Bash command check if string match in command output

I have following command output
$ /opt/CrowdStrike/falconctl -g --aid | grep 'aid='
aid="fdwe234wfgrgf34tfsf23rwefwef3".
I want to check if there is any string after aid= (inside ""). If there is any string, command return code should be 0 and if no value return code must be !=0.
Can someone please help to extend this command to get required output?
Idea is to make sure my bash script to fail if aid= doesn't has any value.
You can use regex to check whether one or more characters exist inside the double quotes. And, you can use regex capture group to extract that value:
if [[ $(/opt/CrowdStrike/falconctl -g --aid | grep 'aid=') =~ ^aid=\"(.+)\"$ ]]; then
aid=${BASH_REMATCH[0]}
echo "aid is $aid"
else
echo "aid not found"
fi
Note that the regex I use is .+ which means 1 or more characters, since you require the string to be non-empty. This is in contrast of the usual .* regex which would have be 0 or more characters.
I don't have falconctl on my system so to mimic its output I'll use a couple files:
$ head falcon*out
==> falcon.1.out <==
some stuff
aid="fdwe234wfgrgf34tfsf23rwefwef3".
some more stuff
==> falcon.2.out <==
some stuff
aid=""
some more stuff
One grep idea:
grep -Eq '^aid="[^"]+"' <filename>
Where:
-E - enable extended regex support
-q - run in silent/quiet mode (suppress all output)
the return code can be captured from $?
Taking for a test drive:
for fname in falcon*out
do
printf "\n############# %s\n" "$fname"
cat "$fname" | grep -Eq '^aid="[^"]+"' "$fname"
echo "return code: $?"
done
This generates:
############# falcon.1.out
return code: 0
############# falcon.2.out
return code: 1

Linux test command with sed is not working

Here is my code which always returns 'false' only:-
export STR="MYC-14:: This is sample string only."
echo $STR
test -z "$(echo "$STR" | sed '/^MYC-/p' )" && echo "true" || echo "false"
I'm trying to match the starting characters "MYC-" from the variable called "STR" but seems like the regular expression within sed condition is wrong due to which test command is returning false.
test -z "$str" succeeds (returns 0) when $str is the empty string. Your sed command is outputting data, so the string is not empty and test is failing (returning non-zero). So the echo "false" branch is executed.
Note that test is not "returning false". It is returning non-zero (eg, it is failing). if does not test boolean conditions, and it is better if you stop thinking about true/false and instead think about success/failure. test failed, because the string it tested was not empty. Because sed generated some output.
If you want to test that a string is not the empty string, use test -n.
By default, sed always outputs the line after processing. Therefore,
echo "$STR" | sed '/^MYC-/p'
will always output the line: once if it doesn't match, twice if it matches.
Use sed -n to tell sed not to print the line by default.
Most shells make it possible to test this without running an external tool. For example, in bash you can write
if [[ $STR = MYC-* ]] ; then
...
fi
Finally, I'm able to make it work:-
export STR="MYC-14:: This is sample string only."
echo $STR
test -z "$(echo "$STR" | sed '/^MYC-/d' )" && echo "truee" || echo "falsee"

How to write a function that check the result of a bash command

I'm trying to write a simple function to debug my script easily and making my code simpler. (Still stuck after 3 hours)
I want to pass to this function 3 arguments
A command
A success string
And an error string
The function is supposed to execute the command and print the proper string whether it's a success or not.
What I mean by successful is when the command prints something in the output.
Here is what I've tried (On CentOS7) :
#!/bin/bash
CMD=$(yum list installed | egrep "yum.utils.\w+" | cut -d " " -f1)
SUCCESS="YES"
ERROR="NO"
foo() {
if ["$1" != ""]; then
echo -e "$2"
else
echo -e "$3"
fi
}
foo $CMD $SUCCESS $ERROR
Unfortunately, I'm encountering 2 problems :
Firstly, when the $CMD is empty, the first parameter will be $SUCCESS instead of an empty string (the behaviour I want)
Secondly, I want to remove the console output (> /dev/null 2>&1 ???).
Do you think it's possible? Do you have any idea how to do it?
Otherwise, is there an easier way with the eval command?
Thanks for reading and have a nice day,
Valentin M.
------------------ Correction ------------------
#!/bin/bash
CMD=$(yum list installed | grep -E "yum.utils.\w+" | cut -d " " -f1)
SUCCESS="YES"
ERROR="NO"
foo() {
if [ "$1" != "" ]; then
echo -e "$2"
else
echo -e "$3"
fi
}
foo "$CMD" "$SUCCESS" "$ERROR"
I found out a similar topic here: Stack overflow : How to write a Bash function that can generically test the output of executed commands?
Unfortunately, I'm encountering 2 problems :
Firstly, when the $CMD is empty, the first parameter will be $SUCCESS instead of an empty string (the behaviour I want)
If you follow the suggestion in William Pursell's comment above, this problem is solved, since an empty first parameter is then passed.
Secondly, I want to remove the console output (> /dev/null 2>&1 ???).
I assume by console output you mean the output to STDERR, since STDOUT is assigned to CMD. Your > /dev/null 2>&1 is unsuitable, as it redirects also STDOUT to /dev/null; just do this with STDERR:
CMD=$(yum list installed 2>/dev/null | egrep "yum.utils.\w+" | cut -d " " -f1)

bash separate parameters with specific delimiter

I am searching for a command, that separates all given parameters with a specific delimiter, and outputs them quoted.
Example (delimiter is set to be a colon :):
somecommand "this is" "a" test
should output
"this is":"a":"test"
I'm aware that the shell interprets the "" quotes before passing the parameters to the command. So what the command should actually do is to print out every given parameter in quotes and separate all these with a colon.
I'm also not seeking for a bash-only solution, but for the most elegant solution.
It is very easy to just loop over an array of these elements and do that, but the problem is that I have to use this inside a gnu makefile which only allows single line shell commands and uses sh instead of bash.
So the simpler the better.
How about
somecommand () {
printf '"%s"\n' "$#" | paste -s -d :
}
Use printf to add the quotes and print every entry on a separate line, then use paste with the -s ("serial") option and a colon as the delimiter.
Can be called like this:
$ somecommand "this is" "a" test
"this is":"a":"test"
apply_delimiter () {
(( $# )) || return
local res
printf -v res '"%s":' "$#"
printf '%s\n' "${res%:}"
}
Usage example:
$ apply_delimiter hello world "how are you"
"hello":"world":"how are you"
As indicated in a number of the comments, a simple "loop-over" approach, looping over each of the strings passed as arguments is a fairly straight-forward way to approach it:
delimit_colon() {
local first=1
for i in "$#"; do
if [ "$first" -eq 1 ]; then
printf "%s" "$i"
first=0
else
printf ":%s" "$i"
fi
done
printf "\n"
}
Which when combined with a short test script could be:
#!/bin/bash
delimit_colon() {
local first=1
for i in "$#"; do
if [ "$first" -eq 1 ]; then
printf "%s" "$i"
first=0
else
printf ":%s" "$i"
fi
done
printf "\n"
}
[ -z "$1" ] && { ## validate input
printf "error: insufficient input\n"
exit 1
}
delimit_colon "$#"
exit 0
Test Input/Output
$ bash delimitargs.sh "this is" "a" test
this is:a:test
Here a solution using the z-shell:
#!/usr/bin/zsh
# this is "somecommand"
echo '"'${(j_":"_)#}'"'
If you have them in an array already, you can use this command
MYARRAY=("this is" "a" "test")
joined_string=$(IFS=:; echo "$(MYARRAY[*])")
echo $joined_string
Setting the IFS (internal field separator) will be the character separator. Using echo on the array will display the array using the newly set IFS. Putting those commands in $() will put the output of the echo into joined_string.

Creating a tshark bash script to export objects

Ok so I've just recently started studying network security, and had no knowledge of linux before doing so. I was trying to write a script that will basically do what the GUI in wireshark does when you follow tcp streams and then export the objects. I have pretty much no background in coding whatsoever and I was wondering the best format to do this in. Everything worked perfectly but then I decided to add a function to test the output against the original with md5sum. I can't get it to work.
function testScript {
if [[ $test == "yes" ]]; then
echo "Type original file path: ";
read ogfpath;
md5sum "$fpath" "$ogfpath" > print
else
echo "Goodbye"
fi
}
echo -n 'Type stream number and press ENTER: '
read stream
echo -n 'Type pcap path and press ENTER: '
read pcap
echo -n 'Type magic number and press ENTER: '
read mnum
echo -n 'Type new file path and press ENTER: '
read fpath
tshark -2 -q -z follow,tcp,raw,$stream -r $pcap | tr '\n' ' ' | sed 's\ \\g' | grep -oP "(?<="$mnum").+" | sed "s/^/"$mnum"/g" | xxd -r -p > $fpath
echo -n 'Do you want to test the program (y/n)? :'
read test
testScript
The problem I see here is that your $test variable is local, only accessible to your function from the inside, in other words, unless it's defined inside the function, it doesn't exist there at all.
One easy way to get around this is to pass parameters to the function, which is very easy in bash. For example:
function test {
if [ "$1" == "yes" ]; then
echo "True!"
else
echo "False!"
fi
}
test "yes"
In this example, the parameter passed to the function "test" is "yes", which is accessed inside the function through the variable $1. More parameters can be passed to the function and accessed sequentially, $2 $3, etc. In your case, your function would have to be called like this:
testScript $test
And the if statement inside the function would have to look like this:
if [[ $1 == "yes" ]]; then

Resources