Rewrite bash command to be ShellCheck compliant - bash

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?".

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 to remove the username/hostname line from an output on Korn Shell?

I run the command
df -gP /data1 /data2 | grep -v File | awk '{print $1}' |
awk -F/dev/ '$0=$2' | tr '\n' '
on the AIX shell (ksh) and it prints the output below:
lv_data01 lv_data02 root#testhost:/
However, I would like the output to be printed this way. Could someone help?
lv_data01 lv_data02
Using grep … | awk … | awk … is not necessary; a single awk could do the whole job. So could sed and it might even be easier. I'd be tempted to deal with the spacing by using:
x=$(df … | sed …); echo $x
The tr command, once corrected, replaces newlines with spaces, so the prompt follows without a newline before it. The ; echo suggestion adds the missing newline; the echo $x suggestion (note no double quotes) does too.
As for the sed command:
sed -n '/File/!{ s/[[:space:]].*//; s%^.*/dev/%%p; }'
Don't print anything by default
If the line doesn't match File (doing the work of grep -v):
remove the first space (blank or tab) and everything after it (doing the work of awk '{print $1}')
replace everything up to /dev/ with nothing and print (doing the work of awk -F/dev/ '{$0=$2}')
The command substitution and capture, followed by echo, deals with spaces and newlines.
So, my suggested solution is:
x=$(df -gP /data1 /data2 | sed -n '/File/!{ s/[[:space:]].*//; s%^.*/dev/%%p; }'); echo $x
You could add unset x after the echo if you are going to be using this directly in the shell and not in a shell script. If it'll be encapsulated in a shell script, you don't have to worry about it.
I'm blithely assuming the output from df -gP won't contain a path such as this, with two occurrences of /dev:
/who/knows/dev/lv_data01/dev/bin
If that's a real problem, you can fix the sed script, but I don't think it will be. It's one thing the second awk script in the question handles differently.

Bash grep variable as an expression

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

bash command substitution escaping

i want to get the result of the following command into a variable.
xprop -name "google-chrome-stable" | grep "window id" | awk '{print $5}' | awk '{print $1}'
the result should look something like that
OUTPUT=xprop -name "google-chrome-stable" | grep "window id" | awk '{print $5}' | awk '{print $1}'
echo $OUTPUT
I know it could be done with command substitution.
The examples in the Link command substitution are not detailed enough because they dont explain how to escape the quotation marks and apostrophes.
Could someone help me find out how to solve that?
It looks like you simply need to do this:
output=$(xprop -name "google-chrome-stable" | awk '/window id/{print $5}')
echo "$output"
There's no need to do any escaping within the $( ). I've wrapped the variable to be echoed in double quotes to prevent things like glob expansion from occurring. As a bonus, I've combined your grep and awk commands and removed the last one which wasn't doing anything useful.
I have also made your variable name lower case. Upper case variable names should be reserved for shell internals. You'll thank me for this one day when you have a variable called $PATH and suddenly everything stops working...
If you are trying to get the group leader window you can use the following instead.
output=$(xprop -notype -f WM_HINTS "32mx" ' ?m6($8)\n' -name google-chrome-stable WM_HINTS | awk '{print $2}')
echo "$output"
Arguments to -f were pulled from the xprop source itself and some man page reading about format and dformat.
The Description section of the xprop man page explains all about format and dformat.

bash invalid delimiter in cut command

tab="`\echo '\t'`"
grep "^.*${tab}.*${tab}.*${tab}.*${tab}.*${tab}" $file |
grep -vi ssm_id |
cut -f 1,5,6 -d "${tab}" > $rmloadfile
I am getting error as
-cut: invalid delimiter
the above code is part of my bash script.
Ignoring the actual problem, you really want to use awk here instead of this combination of grep and cut:
awk 'NF>=6 && tolower($0) !~ ssm_id { print $1, $5, $6 }' $file > $rmloadfile
The echo command doesn't interpret backslash escaped characters by default. It has to be enabled using the -e switch.
If you use:
tab="$(echo -e '\t')"
it works.
But I'd rather recommend using the approach proposed by #devnull in the comments, or refer to the linked question.

Resources