I'm developing a shell script where I have the variable RUN as a result of a command substitution.
Something like this:
RUN="$(kubectl logs ${POD_LISTENER} | grep ${FROM_DATE})"
OUTPUT=$(eval $RUN)
Problem is with the grep portion.
The pattern I'm searching with grep is a date, so I need to add single quote around the variable ${FROM_DATE} to match exactly what I need.
From the terminal, I run the command below and get the result I need
kubectl logs cortex-listener-prod-6b8884d45b-mlmzz | grep '2018-08-11'
And it work well, but I can't make it run from the script.
I don't see, why you need to quote your FROM_DATE, because this string contains only digits and hyphens, and neither one is treated as a filename character in a POSIX shell. However, your outer double quotes don't make sense. Just use
RUN=$(kubectl logs $POD_LISTENER | grep $FROM_DATE)
Related
I have been using a shell script which used to do something like this:
output=$(ls -R /logs/{abc,cde}/"$((${date}/100))"/*/out*${date}* | grep -v "Random" )
echo $output
On running this command, I used to get the files with either abc or cde at relevant location. You can ignore other variables like date etc
However, when I modified the script to take abc,cde as command line parameter instead of hardcoding in the script, it stopped working.
I changed the command to:
output=$(ls -R /logs/{${list}}/"$((${date}/100))"/*/out*${date}* | grep -v "Random" )
where list is abc,cde
I tried a lot of different combinations of quotes etc but it does not seem to be working. Can someone help please with the correct syntax that it works properly
It doesn't work, because the expansion order prevents it.
The order of expansions is: brace expansion; tilde expansion,
parameter and variable expansion
You could solve it with using eval, but eval should be avoided at all.
Probably it's better to use find here.
find /logs -name 'abc/...' -o -name 'cde/...'
This works even with variables
Or use the regex logic.
find /logs/ -regex '/logs/\(abc\|cde\).*'
Try with this
Assign abc and cde to an array
ex -
declare -a ARR=(abc cde)
Assign it to variable like below.
output=ls -R /logs/${ARR[#]/"$((${date}/100))"/*/out*${date}* | grep -v "Random"
Searching pattern and displaying with SED which have double code (") and variable need to pass.
Actual log is:
<confirmation ID="123456-109" status>
Want to Print 109
This is with actual sed command which worked :
sed -n 's%.*confirmation="123456-\(.*\)" status.*%\%p' /tmp/log
output: 109
But when I tried use this in script where passing 123456 as variable it is not working.
req_data=`sed -n 's%.*confirmation="$variable-\(.*\)" status.*%\%p' /tmp/log`
When I run in Script is is not giving me any output.
I am expecting output: 109
Execute a command and assign its output to variable res as res="$(command)".
You need to used sed -E to make parenthesis work for grouping (or in normal mode, you have to escape each parenthesis). (note that -E option of sed is not part of the posix standard)
Also, as stated in the comments, variables are not expanded/interpolated inside single quotes. If you are in a single quoted block, terminate that before the variable and start a different block after the variable.
Following should addresses all the above and should solve your problem.
req_data="$(sed -En 's%.*confirmation ID=\\"'$variable'-(.+)\\" status.*%\1%p' /tmp/log)"
I have a funny issue with grep. Basically, I am trying to match certain control characters in a file and get the count.
grep -ocbUaE $"\x07\|\x08\|\x0B\|\x0C\|\x1A\|\x1B" <file>
Funny enough, in CLI it matches all control characters and returns the correct count, but if I use it in a bash script, it doesn't match anything.
Any ideas what I am doing wrong?
Tested on: MacOS and CentOS - same issue.
Thank you for your help!
I think you should change your command to:
grep -cUaE $'[\x07\x08\x0B\x0C\x1A\x1B]' file
I removed the extra output flags, which get ignored when -c is present. I assume that you include -U and -a for a reason.
The other changes are to use $'' with single quotes (you don't want a double-quoted string here), and replace your series of ORs with a bracket expression, which matches if any one of the characters match.
Note that C-style strings $'' don't work in all shells, so if you want to use bash you should call your script like bash script.sh and/or include the shebang #!/bin/bash if it is executable. sh script.sh does not behave in the same way as bash script.sh.
I want to do (in bash script):
NEWBASE=`echo $NAME | sed "s/${DIR}//g" | sed 's/.\///g'`
I read in the net, that I have to replace single quote with double quote.
This is unfortunately not working. Why? Thanks
sed is overkill for this. Use parameter expansion:
NEWBASE=${NAME//$DIR//}
NEWBASE=${NEWBASE//.\//}
It is important to understand that bash and sed are two completely independent things. When you give bash a command, it first processes it according to its rules, in order to come up with a utility name and a set of arguments for that utility (in this case sed), and then calls the utility with the arguments.
Probably $DIR contains a slash character. Perhaps it looks something like /usr/home/codyline/src.
So when bash substitutes that into the argument to the sed command:
"s/${DIR}//g"
the result is
s//usr/home/codyline/src//g
which is what is then passed to sed. But sed can't understand that commabnd: it has (many) too many / characters.
If you really want to use sed for this purpose, you need to use a delimiter other than /, and it needs to be a character you are confident will never appear in $DIR. Fortunately, the sed s command allows you to use any character as a delimiter: whatever character follows the s is used as the delimiter. But there always must be exactly three of them in the command.
For example, you might believe that no directory path contains a colon (:), in which case you could use:
sed "s:${DIR}::g"
Of course, someday that will fail precisely because you have a directory with a colon in its name. So you could make things more general by using bash's substitute-and-replace feature to backslash-escape all the colons:
sed "s:${DIR//:/\:}::g"
But you could have used this bash feature in order to avoid the use of sed altogether:
NEWBASE=${NAME//$DIR}
Unfortunately, you can't nest bash substitute-and-replaces, so you need to do them sequentially:
NEWBASE=${NEWBASE//.\/}
Note: I used ${var//...}, which is the equivalent of specifying the g flag in a sed s command, but I really don't know if it is appropriate. Do you really expect multiple instances of $DIR in a single path? If there are multiple instances, do you really want to remove all of them? You'll have to decide.
I'm having a little issue getting quite a simple bash script running.
The part that's working:
qstat -f $queuenum | grep -Po '(?<=PBS_O_WORKDIR=).*(?=,)'
Outputs a directory to the screen (for example):
/short/h72/SiO2/defected/2-999/3-forces/FORCES_364
All I want to do is change directory to this folder. Appending a "| cd" to the end of the above command doesn't work, and I can't quite figure out how to use the $(()) tags either.
Any help would be appreciated.
cd `qstat -f $queuenum | grep -Po '(?<=PBS_O_WORKDIR=).*(?=,)' `
Invoking your script creates a new bash shell
This shell is destroyed when your script ends.
If you use exec <scriptname> to run your script, the new bash shell is substituted for the current one. So if you add the command bash at the end of your script, you will get what you desire, but not the same bash shell.
You should use:
cd "$(qstat -f $queuenum | grep -Po '(?<=PBS_O_WORKDIR=).*(?=,)' )"
you are trying to achieve command substitution which is achieved by using either of these two syntax:
$(command)
or like this using backticks:
`command`
The first one is the preferred way as it allows nesting of command substitutions something like:
foo=$(command1 | command2 $(command3))
also you should enclose the entire command substitution in double quotes to protect you if the result of the command substitution is a string with spaces.