Bash grep variable as an expression - bash

I have a problem with bash. I have big log file and I must check only a part of all log. In this purpose I use those expressions:
cat 29.log | grep -A 999 "15/02/06-22:30"
or
awk '$1>="15/02/06-22:30" {print$0}' 29.log
I want to change "15/02/06-22:30" at "date +%y/%m/d-%H:M" but when I use command
awk '$1>="date +%y/%m/d-%H:M" {print$0}' 29.log
or
awk '$1>='date +%y/%m/d-%H:M' {print$0}' 29.log
nothing happens.
Any ideas?
I need this in one command, not a script

You can pass shell variables to AWK using the -v flag:
awk -v d="$(date '+%y/%m/%d-%H:%M')" '$1>=d' 29.log

grep -A 999 `date '+%y/%m/d-%H:M'` 29.log

Related

One-liner POSIX command to lowercase string in bash

Problem
I have this comand:
sed $((SS - default_scripts))!d customScripts.txt
and it gives me Foo Bar.
I want to convert this to lowercase.
Attempt
When I tried using the | awk '{print tolower($0)}' command on it it returned nothing:
$($(sed $((SS - default_scripts))!d customScripts.txt) | awk '{print tolower($0)}')
Final
Please enlighten me on my typo, or recommend me another POSIX way of converting a whole string to lowercase in a compact manner. Thank you!
The pipe to awk should be inside the same command substitution as sed, so that it processes the output of sed.
$(sed $((SS - default_scripts))!d customScripts.txt | awk '{print tolower($0)}')
You don't need another command substitution around both of them.
Your typo was wrapping everything in $(...) and so first trying to execute the output of just the sed part and then trying to execute the output of the sed ... | awk ... pipeline.
You don't need sed commands nor shell arithmetic operations when you're using awk. If I understand what you're trying to do with this:
$(sed $((SS - default_scripts))!d customScripts.txt) | awk '{print tolower($0)}'
correctly then it'd be just this awk command:
awk -v s="$SS" -v d="$default_scripts" 'BEGIN{n=s-d} NR==n{print tolower($0); exit}' customScripts.txt

How can I capture all numbers in a string using sed

I tried to use sed to capture numbers in a string with following script:
echo '["770001,德邦优化混合","750005,安信平稳增长混合发起A"]' | sed -n 's/.*"\(\d{6}\),/\1/p'
My expectation is echo
770001
750005
While nothing output. Why?
In case you are ok with awk then following awk may help you in same. Since I have old version of awk so I am using --re-interval if you have newer version of awk then you may not need it.
echo '["770001,德邦优化混合","750005,安信平稳增长混合发起A"]' |
awk --re-interval '{while(match($0,/[0-9]{6}/)){print substr($0,RSTART,RLENGTH);$0=substr($0,RSTART+RLENGTH+1)}}'
Output will be as follows.
770001
750005

Rewrite bash command to be ShellCheck compliant

How can I rewrite the following bash command to be ShellCheck compliant?
memory=$(cat /proc/meminfo | grep 'MemTotal:' | awk {'print $2}' 2> /dev/null)
It is currently complaining about:
Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..'
This { is literal.
The shellcheck complaints are
Using cat filename | grep 'pattern' instead of grep 'pattern' filename
The first brace in the awk command is on the outside of the single quote, hence literal; it should be awk '{command}'
So, a version that would satisfy shellcheck would look like
memory=$(grep 'MemTotal:' /proc/meminfo | awk '{print $2}')
I'm not sure why you redirected standard error, so I dropped it.
However, piping grep output to awk is rarely the best solution; awk can do almost anything grep can, so you could further simplify to
memory=$(awk '/MemTotal:/ { print $2 }' /proc/meminfo)
No pipes!
Just as a guess, you probably want:
memory=$(grep 'MemTotal:' /proc/meminfo | awk '{print $2}' 2> /dev/null)
However, that's a direct interpretation of the shellcheck output, so I am unsure as to what you are asking about. As it stands, you are essentially asking: "Why isn't this working?".

Multiple argument bash script for awk processing

Is there a way to process 2 different files passed as arguments to a bash script which uses awk.
Script signature:
./statistical_sig.sh path_to_reviews_folder hotel_1 hotel_2
I tried the following but only the first argument got processed.
hotel1="$2";
hotel2="$3";
dos2unix -U $hotel1 | dos2unix -U $hotel2 | echo "$hotel1" "$hotel2" | xargs | awk -v hotel1="$hotel1" -v hotel2="$hotel2" { .. code ..}
You don't need all these pipes to run awk.
Either you will use something like this if you plan to read with awk some other files and use hotel1 and hotel2 somehow inside your awk code:
awk -v hotel1=$(dos2unix -U "$hotel1") -v hotel2=$(dos2unix -U "$hotel2") { awk code ..} file1 file2
Or you will use this if you plan to read and process contents of files hotel1 and hotel2:
awk { awk code ..} <(dos2unix -U "$hotel1") <(dos2unix -U "$hotel2")
Alternativelly you can modify your code like this, but this is less efficient :
hotel1=$(dos2unix "$hotel1") && hotel2=$(dos2unix "$hotel2") && echo "$hotel1 $hotel2" | awk '{your code here}'
If you explain better your question advising what is the awk code and what you are trying to achieve, you will get better advises.

shell command to truncate/cut a part of string

I have a file with the below contents. I got the command to print version number out of it. But I need to truncate the last part in the version file
file.spec:
Version: 3.12.0.2
Command used:
VERSION=($(grep -r "Version:" /path/file.spec | awk '{print ($2)}'))
echo $VERSION
Current output : 3.12.0.2
Desired output : 3.12.0
There is absolutey no need for external tools like awk, sed etc. for this simple task if your shell is POSIX-compliant (which it should be) and supports parameter expansion:
$ cat file.spec
Version: 3.12.0.2
$ version=$(<file.spec)
$ version="${version#* }"
$ version="${version%.*}"
$ echo "${version}"
3.12.0
Try this:
VERSION=($(grep -r "Version:" /path/file.spec| awk '{print ($2)}' | cut -d. -f1-3))
Cut split string with field delimiter (-d) , then you select desired field with -f param.
You could use this single awk script awk -F'[ .]' '{print $2"."$3"."$4}':
$ VERSION=$(awk -F'[ .]' '{print $2"."$3"."$4}' /path/file.spec)
$ echo $VERSION
3.12.0
Or this single grep
$ VERSION=$(grep -Po 'Version: \K\d+[.]\d+[.]\d' /path/file.spec)
$ echo $VERSION
3.12.0
But you never need grep and awk together.
if you only grep single file, -r makes no sense.
also based on the output of your command line, this grep should work:
grep -Po '(?<=Version: )(\d+\.){2}\d+' /path/file.spec
gives you:
3.12.0
the \K is also nice. worked for fixed/non-fixed length look-behind. (since PCRE 7.2). There is another answer about it. but I feel look-behind is easier to read, if fixed length.

Resources