how can you change a column of numbers to a space separated list in bash - bash

How can i take the output of this command...
ps -ef | grep ^apache | grep /sbin/httpd | awk '{print $2}'
16779
16783
16784
16785
16786
16787
16788
16789
16790
16794
16795
16796
16797
16799
16800
16801
16802
16803
16804
16805
...so a single column of numbers... and transform those numbers into a single line of numbers separated by a " -p "... This would be used for the following...
lsof -p 16779 -p 16783 -p 16784 ...

Pipe into
sed 's/^/-p /' | tr '\n' ' '

If you have it available, pidof would be more convenient:
lsof $(pidof apache | sed 's/^\| / -p /g')

You could pipe into awk:
awk 'BEGIN { printf "lsof" } { printf " -p %s", $1 } END { printf "\n" }'
Result:
lsof -p 16779 -p 16783 -p 16784 -p 16785 -p 16786 -p 16787 -p 16788 -p 16789 -p 16790 -p 16794 -p 16795 -p 16796 -p 16797 -p 16799 -p 16800 -p 16801 -p 16802 -p 16803 -p 16804 -p 16805

tmp="lsof "
for i in `ps -ef | awk '/^apache/ && /httpd/ {print $2}'`;
do
tmp=${tmp}" -p "${i}" ";
done
echo $tmp
Should do the trick

In a command substitution, the newlines from the pipeline will be converted to spaces.
pids=$( ps -ef | awk '/^apache/ && /\/sbin\/httpd/ {print $2}' ) )
Then a call to printf can be used to format the options for lsof. The format string is repeated as necessary for each argument contained in pids.
lsof $( printf "-p %s " $pids )

Add the following code to your one liner:
awk '{print $0 " -p "}' | tr '\n' ' ' | awk -F " " '{print "lsof -p " $0}'
Final code :
ps -ef | grep ^apache | grep /sbin/httpd | awk '{print $2}' | awk '{print $0 " -p "}' | tr '\n' ' ' | awk -F " " '{print "lsof -p " $0}'

Related

Removing string from keychain output

After running
test=$(security 2>&1 >/dev/null find-generic-password -ga test) echo
$test
The output is
password: "1234"
I would like to remove everything and only leave the actual password, in these case just
1234
Any help?
If the format is always password: "value", you can do this efficiently without any external utility using just substring expansion:
echo "${test:11:-1}" #output: 1234
If you insist on using other utilities:
awk -F'"' '{ print $2 }' <<< "$test" #output: 1234
cut -d'"' -f2 <<< "$test" #output: 1234
Both commands above will fail if you have a " character in your password. Another solution using sed working fine with " in your password:
sed 's/^password: "\(.*\)"$/\1/' <<< "$test" #output: 1234
You can solve it by:
command:
echo 'password: "1234"' | awk -F"\"" '{print $2}'
output:
1234
Use a Perl-Compatible Regular Expression with Grep
If your system has a grep compiled with the PCRE engine (e.g. pcregrep, or support for grep -P) then you can drop pcregrep -o ': "\K[^"]+' into your pipeline. For example, to send just the material between the quotes to standard output:
$ echo 'password: "1234"' | pcregrep -o ': "\K[^"]+'
1234
$ echo 'password: "ABCD"' | pcregrep -o ': "\K[^"]+'
ABCD
$ echo 'password: "1A2B3C4D"' | pcregrep -o ': "\K[^"]+'
1A2B3C4D

Why does my awk redirection not work?

Im trying to redirect my output to replace the contents of my file but if I do this it doesn't change my output at all
#!/bin/bash
ssh_config_path="$HOME/.ssh/config"
temp_ssh_config_path="$HOME/.ssh/config_temporary"
new_primary_username=$1
curr_primary_username=`awk '/^Host github\.com$/,/#Username/{print $2}' $ssh_config_path | tail -1`
new_user_name=`awk "/^Host github-$new_primary_username$/,/#Name/{print $2}" $ssh_config_path | tail -1 | sed 's/#Name //' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'`
new_user_email=`awk "/^Host github-$new_primary_username$/,/#Email/{print $2}" $ssh_config_path | tail -1 | sed 's/#Email //' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'`
echo "Switching from $curr_primary_username to $new_primary_username"
echo "Setting name to $new_user_name"
echo "Setting email to $new_user_email"
awk "
!x{x=sub(/github-$new_primary_username/,\"github.com\")}
!y{y=sub(/github\.com/,\"github-$curr_primary_username\")}
1" $ssh_config_path > temp_ssh_config_path && mv temp_ssh_config_path ssh_config_path
but if I do this I get the correct output on my terminal screen
#!/bin/bash
ssh_config_path="$HOME/.ssh/config"
temp_ssh_config_path="$HOME/.ssh/config_temporary"
new_primary_username=$1
curr_primary_username=`awk '/^Host github\.com$/,/#Username/{print $2}' $ssh_config_path | tail -1`
new_user_name=`awk "/^Host github-$new_primary_username$/,/#Name/{print $2}" $ssh_config_path | tail -1 | sed 's/#Name //' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'`
new_user_email=`awk "/^Host github-$new_primary_username$/,/#Email/{print $2}" $ssh_config_path | tail -1 | sed 's/#Email //' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'`
echo "Switching from $curr_primary_username to $new_primary_username"
echo "Setting name to $new_user_name"
echo "Setting email to $new_user_email"
awk "
!x{x=sub(/github-$new_primary_username/,\"github.com\")}
!y{y=sub(/github\.com/,\"github-$curr_primary_username\")}
1" $ssh_config_path
It's disappointing how far you've veered from the answers you were given but in any case here's the correct syntax for your script (untested since you didn't provide any sample input/output):
#!/bin/bash
ssh_config_path="$HOME/.ssh/config"
temp_ssh_config_path="$HOME/.ssh/config_temporary"
new_primary_username="$1"
curr_primary_username=$(awk 'f&&/#Username/{print $2; exit} /^Host github\.com$/{f=1}' "$ssh_config_path")
new_user_name=$(awk -v npu="$new_primary_username" 'f&&/#Name/{print $2; exit} $0~"^Host github-"npu"$"{f=1}' "$ssh_config_path")
new_user_email=$(awk -v npu="$new_primary_username" 'f&&/#Email/{print $2; exit} $0~"^Host github-"npu"$"{f=1}' "$ssh_config_path")
echo "Switching from $curr_primary_username to $new_primary_username"
echo "Setting name to $new_user_name"
echo "Setting email to $new_user_email"
awk -v npu="$new_primary_username" -v cpu="$curr_primary_username" '
!x{x=sub("github-"npu,"github.com")}
!y{y=sub(/github\.com/,"github-"cpu)}
1' "$ssh_config_path" > temp_ssh_config_path && mv temp_ssh_config_path "$ssh_config_path"
By doing that I noticed that your last statement was:
mv temp_ssh_config_path ssh_config_path
when you probably meant:
mv temp_ssh_config_path "$ssh_config_path"
and that would have caused a problem with your expected output file being empty.
The whole thing should, of course, have been written as just 1 simple awk script.

BASH: Remove newline for multiple commands

I need some help . I want the result will be
UP:N%:N%
but the current result is
UP:N%
:N%
this is the code.
#!/bin/bash
UP=$(pgrep mysql | wc -l);
if [ "$UP" -ne 1 ];
then
echo -n "DOWN"
else
echo -n "UP:"
fi
df -hl | grep 'sda1' | awk ' {percent+=$5;} END{print percent"%"}'| column -t && echo -n ":"
top -bn2 | grep "Cpu(s)" | \sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | \awk 'END{print 100 - $1"%"}'
You can use command substitution in your first sentence (notice you're creating a subshell in this way):
echo -n $(df -hl | grep 'sda1' | awk ' {percent+=$5;} END{print percent"%"}'| column -t ):

To get \n instead of n in echo -e command in shell script

I am trying to get the output for the echo -e command as shown below
Command used:
echo -e "cd \${2}\nfilesModifiedBetweenDates=\$(find . -type f -exec ls -l --time-style=full-iso {} \; | awk '{print \$6,\$NF}' | awk '{gsub(/-/,\"\",\$1);print}' | awk '\$1>= '$fromDate' && \$1<= '$toDate' {print \$2}' | tr \""\n"\" \""\;"\")\nIFS="\;" read -ra fileModifiedArray <<< "\$filesModifiedBetweenDates"\nfor fileModified in \${fileModifiedArray[#]}\ndo\n egrep -w "\$1" "\$fileModified" \ndone"
cd ${2}
Expected output:
cd ${2}
filesModifiedBetweenDates=$(find . -type f -exec ls -l --time-style=full-iso {} \; | awk '{print $6,$NF}' | awk '{gsub(/-/,"",$1);print}' | awk '$1>= '20140806' && $1<= '20140915' {print $2}' | tr "\n" ";")
IFS=; read -ra fileModifiedArray <<< $filesModifiedBetweenDates
for fileModified in ${fileModifiedArray[#]}
do
egrep -w $1 $fileModified
done
Original Ouput:
cd ${2}
filesModifiedBetweenDates=$(find . -type f -exec ls -l --time-style=full-iso {} \; | awk '{print $6,$NF}' | awk '{gsub(/-/,"",$1);print}' | awk '$1>= '20140806' && $1<= '20140915' {print $2}' | tr "n" ";")
IFS=; read -ra fileModifiedArray <<< $filesModifiedBetweenDates
for fileModified in ${fileModifiedArray[#]}
do
egrep -w $1 $fileModified
done
How can i handle "\" in this ?
For long blocks of text, it's much simpler to use a quoted here document than trying to embedded a multi-line string into a single argument to echo or printf.
cat <<"EOF"
cd ${2}
filesModifiedBetweenDates=$(find . -type f -exec ls -l --time-style=full-iso {} \; | awk '{print $6,$NF}' | awk '{gsub(/-/,"",$1);print}' | awk '$1>= '20140806' && $1<= '20140915' {print $2}' | tr "\n" ";")
IFS=; read -ra fileModifiedArray <<< $filesModifiedBetweenDates
for fileModified in ${fileModifiedArray[#]}
do
egrep -w $1 $fileModified
done
EOF
You'd better use printf to have a better control:
$ printf "tr %s %s\n" '"\n"' '";"'
tr "\n" ";"
As you see, we indicate the parameters within double quotes: printf "text %s %s" and then we define what content should be stored in this parameters.
In case you really have to use echo, then escape the \:
$ echo -e 'tr "\\n" ";"'
tr "\n" ";"
Interesting read: Why is printf better than echo?

Change in format for awk

My line of code is below.
awk 'BEGIN {printf "gnome-terminal"}
{printf " --tab -e \"telnet "$4" "$6 " | tee " $1$12"\" -t \"" $1" "$12 "\"" }
END {printf "\n"}' temp1.prm >> abc
Output gives this in abc:
gnome-terminal --tab -e "telnet 10.31.248.104 3007 | tee dutA1MM1" -t "dutA1 MM1"
I have to get below format:
gnome-terminal --tab -e 'bash -c "telnet 10.31.248.104 3007 | tee script1.log"' -t "dutA1 MM1"
Can anyone help ?
Try this double-quotes quoted format:
awk "BEGIN {printf \"gnome-terminal\"} {printf \" --tab -e 'bash -c \\\"telnet \"\$4\" \"\$6 \" | tee \" \$1\$12\"\\\"' -t \\\"\" \$1\" \"\$12 \"\\\"\" } END { printf \"\\n\"}" temp1.prm >> abc
Testing with echo, the argument to awk would literally be
BEGIN {printf "gnome-terminal"} {printf " --tab -e 'bash -c \"telnet "$4" "$6 " | tee " $1$12"\"' -t \"" $1" "$12 "\"" } END { printf "\n"}
Don't get into a quoting nightmare. You could keep things tidy like so:
BEGIN {
double_quote = "\""
s1 = "gnome-terminal --tab -e 'bash -c "
s2 = double_quote "telnet 10.31.248.104 3007 | tee script1.log" double_quote
s3 = "' -t dutA1 MM1"
printf "%s%s%s\n",s1,s2,s3
}
You probably want something like this:
awk '{ printf "gnome-terminal --tab -e \047bash -c \"telnet %s %s | tee script1.log\"\047 -t \"%s %s\"\n", $4, $6, $1, $12 }' file
but since you didn't provide sample input and expected output it's just a guess.

Resources