"Merge" paths and display all matchs in one line - bash

I need help, I have that :
/usr/include/slang.h:include
/usr/include/slang.h:star
/usr/include/slang.h:load
/usr/include/byteswap.h:include
and I must merge to have result here in shell:
/usr/include/slang.h include star load
/usr/include/byteswap.h include
How can I do ?

$ cat merge.txt
/usr/include/slang.h:include
/usr/include/slang.h:star
/usr/include/slang.h:load
/usr/include/byteswap.h:include
$ cat merge.sh
#!/bin/bash
for path in $(awk -F':' '{print $1}' merge.txt | uniq)
do
values=$(grep "${path}" merge.txt | awk -F':' '{print $NF}' | tr '\n' ' ')
echo "${path}" "${values}"
done
Output:
$ ./merge.sh
/usr/include/slang.h include star load
/usr/include/byteswap.h include

Related

How to grab fields in inverted commas

I have a text file which contains the following lines:
"user","password_last_changed","expires_in"
"jeffrey","2021-09-21 12:54:26","90 days"
"root","2021-09-21 11:06:57","0 days"
How can I grab two fields jeffrey and 90 days from inverted commas and save in a variable.
If awk is an option, you could save an array and then save the elements as individual variables.
$ IFS="\"" read -ra var <<< $(awk -F, '/jeffrey/{ print $1, $NF }' input_file)
$ $ var2="${var[3]}"
$ echo "$var2"
90 days
$ var1="${var[1]}"
$ echo "$var1"
jeffrey
while read -r line; do # read in line by line
name=$(echo $line | awk -F, ' { print $1} ' | sed 's/"//g') # grap first col and strip "
expire=$(echo $line | awk -F, ' { print $3} '| sed 's/"//g') # grap third col and strip "
echo "$name" "$expire" # do your business
done < yourfile.txt
IFS=","
arr=( $(cat txt | head -2 | tail -1 | cut -d, -f 1,3 | tr -d '"') )
echo "${arr[0]}"
echo "${arr[1]}"
The result is into an array, you can access to the elements by index.
May be this below method will help you using
sed and awk command
#!/bin/sh
username=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $1}')
echo "$username"
expires_in=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $3}')
echo "$expires_in"
Output :
jeffrey
90 days
Note :
This above method will work if their is only distinct username
As far i know username are not duplicate

How to find list of groups that are present in '/etc/passwd' but not in the '/etc/group'?

I want to find list of groups that are present in /etc/passwd but not in the /etc/group
I have written the following command so far
for user in $(getent passwd | cut -d: -f1); do
printf "%s: %s\n" $user "$(id -nG $user)"
done
$ id -Gz | cat -v
197121^#114^#197610^#544^#545^#4^#66049^#11^#15^#113^#4095^#66048^#262154^#405504^#$
$ getent passwd | tr '[:alpha:]' '#'
########:*:197609:197121:#-#######53\########,#-1-5-21-2486228713-2700429697-662227502-1001:/####/########:/###/####
##############:*:544:544:#-#######\##############,#-1-5-32-544:/:/####/#######
######:*:18:18:#-## #########\######,#-1-5-18:/####/######:/###/####
##### #######:*:19:19:#-## #########\##### #######,#-1-5-19:/:/####/#######
####### #######:*:20:20:#-## #########\####### #######,#-1-5-20:/:/####/#######
##############:*:544:544:#-#######\##############,#-1-5-32-544:/:/####/#######
## #######+################:*:328384:328384:#-## #######\################,#-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464:/:/####/#######
$ awk 'NR==FNR{grps[$0];next} !($3 in grps){print $3}' RS='\0' <(id -Gz) RS='\n' FS=':' <(getent passwd)
197609
18
19
20
328384
Could you please try following, where it will give entries of those group names which are present in /etc/passwd and NOT in /etc/group.
awk -F':' 'FNR==NR{a[$5]=$0;next} ($1 in a){delete a[$1]} END{for(i in a){print a[i]}}' /etc/passwd /etc/group
with grep/cut
$ grep -vxFf <(cut -d: -f1 </etc/group) <(cut -d: -f1 </etc/passwd)

Bash Cut text from line with different delimiters

I have a variable with value like:
#capability_ids type="list">[LOADBALANCER]</capability_ids>#
And need to extract from this string type of equipment ( LOADBALANCER ).
I've tried to use cut, but don't know how write cut command with different delimiters.
DeviceType=$( echo $DeviceTypeDirty | cut -d'[' -f1)
Can enywone help me with right solution on bash?
use awk with regular expression: awk -F '[\\[\\]]' '{print $2}'
$ echo '#capability_ids type="list">[L3SWITCH]/capability_ids>#'|awk -F '[\\[\\]]' '{print $2}'
$ L3SWITCH
$ DeviceType=$( echo "$DeviceTypeDirty" | awk -F '[\\[\\]]' '{print $2}')
I tried and got to extract "LOADBALANCER"
Administrators-MacBook-Pro:~$ echo "\"list\">[LOADBALANCER]
</capability_ids>#"|awk -F '[][]' '{print $2}'
LOADBALANCER
Administrators-MacBook-Pro:~$
Hope that helps!
Using cut:
DeviceTypeDirty="#capability_ids type="list">[LOADBALANCER]</capability_ids>#"
DeviceType="$(echo "$DeviceTypeDirty" | cut -d'[' -f2 | cut -d']' -f1)"
Output:
echo "$DeviceType"
LOADBALANCER

Print out onto same line with ":" separating variables

I have the following piece of code and would like to display HOST and RESULT side by side with a : separating them.
HOST=`grep pers results.txt | cut -d':' -f2 | awk '{print $1}'`
RESULT=`grep cleanup results.txt | cut -d':' -f2 | awk '{print $1}' | sed -e 's/K/000/' -'s/M/000000/'`
echo ${HOST}${RESULT}
Please can anyone assist with the final command to display these, I am just getting all of hosts and then all of results.
You probably want this:
HOST=( `grep pers results.txt | cut -d':' -f2 | awk '{ print $1 }'` ) #keep the output of the command in an array
RESULT=( `grep cleanup results.txt | cut -d':' -f2 | awk '{ print $1 }' | sed -e 's/K/000/' -'s/M/000000/'` )
for i in "${!HOST[#]}"; do
echo "${HOST[$i]}:${RESULT[$i]}"
done
A version that works without arrays, using an extra file handle to read from 2 sources at at time.
while read host; read result <&3; do
echo "$host:$result"
done < <( grep peers results.txt | cut -d: -f2 | awk '{print $1}' ) \
3< <( grep cleanup results.txt | cut -d':' -f2 | awk '{print $1}' | sed -e 's/K/000/' -'s/M/000000/')
It's still not quite POSIX, as it requires process substitution. You could instead use explicit fifes. (Also, an attempt to shorten the pipelines that produce the hosts and results. It's probably possible to combine this into a single awk command, since you can either do the substitution in awk, or pipe to sed from within awk. But this is all off-topic, so I leave it as an exercise to the reader.)
mkfifo hostsrc
mkfifo resultsrc
awk -F: '/peers/ {split($2, a, ' '); print a[1]}' results.txt > hostsrc &
awk -F: '/cleanup/ {split($2, a, ' '); print a[1]}' results.txt | sed -e 's/K/000' -e 's/M/000000/' > resultsrc &
while read host; read result <&3; do
echo "$host:$result"
done < hostsrc 3< resultsrc

Bash: "xargs cat", adding newlines after each file

I'm using a few commands to cat a few files, like this:
cat somefile | grep example | awk -F '"' '{ print $2 }' | xargs cat
It nearly works, but my issue is that I'd like to add a newline after each file.
Can this be done in a one liner?
(surely I can create a new script or a function that does cat and then echo -n but I was wondering if this could be solved in another way)
cat somefile | grep example | awk -F '"' '{ print $2 }' | while read file; do cat $file; echo ""; done
Using GNU Parallel http://www.gnu.org/software/parallel/ it may be even faster (depending on your system):
cat somefile | grep example | awk -F '"' '{ print $2 }' | parallel "cat {}; echo"
awk -F '"' '/example/{ system("cat " $2 };printf "\n"}' somefile

Resources