Awk print exact fields when finding an exact match - bash

I have a persons.dat file containing information.
Here's an example line.
1129|Lepland|Carmen|female|1984-02-18|228T04:39:58.781+0000|81.25.252.111|Internet Explorer
1129 is the ID.
I am asked to display the information of anyone based on their ID,in particular their firstname (Carmen), (Lastname = Lepland) and date of Birth (1984-02-18) separated by a space.
I have stored the id in a shell variable IDNumber as shown below:
for arg1 in $#;do # Retrieve ID Number
if [ $1 = "-id" ];then
IDNumber="$2"
fi
shift
done
How can I use awk to display the exact fields of one ID?

The command line argument parsing of the shell script is a bit confusing like that, since arg1 is not used.
And even after it finds -id and assigns $2 to IDNumber,
the iteration continues.
For example when the arguments are -id 3,
after IDNumber=3,
the iteration continues, checking if [ 3 = "-id" ].
Also, the "$1" in if [ $1 = ... ] should be double-quoted,
otherwise the script will crash if there is an empty argument.
Here's one way to fix these issues:
while [ $# -gt 0 ]; do
if [ "$1" = -id ]; then
id=$2
fi
shift
done
Then you can use id with Awk like this:
awk -F'|' -v id="$id" '$1 == id {print $3, $2, $5}' persons.dat
That is:
Set | as the field separator
Set id variable in Awk to the value of $id in the shell
Find the record in the input where the first field ($1) is equal to id
Print the columns you need

Related

How to send shell script output in a tablular form and send the mail

I am a shell script which will give few lines as a output. Below is the output I am getting from shell script. My script flow is like first it will check weather we are having that file, if I am having it should give me file name and modified date. If I am not having it should give me file name and not found in a tabular form and send email. Also it should add header to the output.
CMC_daily_File.xlsx Not Found
CareOneHMA.xlsx Jun 11
Output
File Name Modified Date
CMC_daily_File.xlsx Not Found
CareOneHMA.xlsx Jun 11
UPDATE
sample of script
#!/bin/bash
if [ -e /saddwsgnas/radsfftor/coffe/COE_daily_File.xlsx ]; then
cd /sasgnas/radstor/coe/
ls -la COE_daily_File.xlsx | awk '{print $9, $6"_"$7}'
else
echo "CMC_COE_daily_File.xlsx Not_Found"
fi
Output
CMC_COE_daily_File.xlsx Jun_11
I thought I might offer you some options with a slightly modified script. I use the stat command to obtain the file modification time in more expansive format, as well as specifying an arbitrary, pre-defined, spacer character to divide the column data. That way, you can focus on displaying the content in its original, untampered form. This would also allow the formatted reporting of filenames which contain spaces without affecting the logic for formatting/aligning columns. The column command is told about that spacer character and it will adjust the width of columns to the widest content in each column. (I only wish that it also allowed you to specify a column divider character to be printed, but that is not part of its features/functions.)
I also added the extra AWK action, on the chance that you might be interested in making the results stand out more.
#!/bin/sh
#QUESTION: https://stackoverflow.com/questions/74571967/how-to-send-shell-script-output-in-a-tablular-form-and-send-the-mail
SPACER="|"
SOURCE_DIR="/saddwsgnas/radsfftor/coe"
SOURCE_DIR="."
{
printf "File Name${SPACER}Modified Date\n"
#for file in COE_daily_File.xlsx
for file in test_55.sh awkReportXmlTagMissingPropertyFieldAssignment.sh test_54.sh
do
if [ -e "${SOURCE_DIR}/${file}" ]; then
cd "${SOURCE_DIR}"
#ls -la "${file}" | awk '{print $9, $6"_"$7}'
echo "${file}${SPACER}"$(stat --format "%y" "${file}" | cut -f1 -d\. | awk '{ print $1, $2 }' )
else
echo "${file}${SPACER}Not Found"
fi
done
} | column -x -t -s "|" |
awk '{
### Refer to:
# https://man7.org/linux/man-pages/man4/console_codes.4.html
# https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
if( NR == 1 ){
printf("\033[93;3m%s\033[0m\n", $0) ;
}else{
print $0 ;
} ;
}'
Without that last awk command, the output session for that script was as follows:
ericthered#OasisMega1:/0__WORK$ ./test_55.sh
File Name Modified Date
test_55.sh 2022-11-27 14:07:15
awkReportXmlTagMissingPropertyFieldAssignment.sh 2022-11-05 21:28:00
test_54.sh 2022-11-27 00:11:34
ericthered#OasisMega1:/0__WORK$
With that last awk command, you get this:

how to check whether the input is found or not found in the directory using pinky (there are inputs, but the user is not there)

what I want is to input a username and if the user cannot be found, the FNAME should be not found, but when I did the tester, the NOTFOUND never shows up, the tester was made by someone else and should have no problem.
function fname()
{
#if argument passed canot be found among sessions logged in
result=$(pinky -f "$1")
result_length="${#result}"
#if the result length is not equal to zero means there are some values
elif [ "$result_length" != 0 ]
then
FNAME="$(pinky -f $1 | awk '{print $2}')"
return 0
elif [ ! -f "$result" ]
then
FNAME="NOTFOUND"
return 0
fi
}
I tried to check the result but only ERROR and the user's first name can be displayed, the NOTFOUND never shows up even when I put a wrong input. is it because the ${# result} never display 0?
fname
Function status code is ==1== FNAME value is ==ERROR==
[[[[ WORKS - but user id is not found ]]]]
fname nouser
Function status code is ==0== FNAME value is ====
[[[[ WORKS - user id is found ]]]]
fname zo9
Function status code is ==0== FNAME value is ==Zo==
Your issue is on this line:
elif [ ! -f "$result" ]
This literally means "else if $result is not a file." Since you are setting result to the output of pinky, this is obviously not doing what you think it does. Since you are checking whether the variable result is blank or not in the original if statement, all you need here is else.
Also, there is a built in way to check for a blank variable using test ([). You could test with the -n option. It would be cleaner to use that in your if block like this:
if [ -n "$result" ]; then
# found
else
# not found
fi
Then, there is no need for the result_length variable.
Also, there is no need to re-run pinky for awk. You have the result of pinky stored in your result variable. All you need to do is send the variable into awk with a here-string. Something like this:
FNAME="$(awk '{print $2}' <<< "$result")"

Storing data in shell

I have a need to store a list of e-mails in a shell script. This script will get called and passed a customer number. depending on the customer number I want to populate a variable based on the passed in customer number.
I am not sure how to accomplish this and have been looking.
command example
gcb "type" "customernumber" "date"
I want to pull an e-mail associated with that customer number and populate a variable with it.
I would prefer this get stored in the script and not in a separate file if possible.
#shellter
So as you can see above my command has the customer number as $2, i am trying to get the email finder to work with that in mind. So I created a script to test the e-mail finder function with. It works fine as you have it below, but if i want it to look for $2 == cust_id it returns nothing. Here is my code below.
#!/bin/sh
#case $# in 0 ) echo "usage: myEmailFinder2 CustID" ; exit 1 ;; esac
cfgDir="/verification"
# given cust file like
# cust_id "\t" email_addr
fn_myEmailFinder() {
awk -F"\t" -v cust_id="$2" '{if ($2 == cust_id) {print $3}}' /verification/custlist.cfg
}
emailAddr=$( fn_myEmailFinder "$1")
echo $emailAddr
The command I run to test this is this
sh emailtest.sh test 90624
My config file is layed out like this, tab delimited
CustomerNumber CustomerName Email
I am going to store more data in this file to populate other variables, I'm sure once i get this figured out, I can sort out the other data.
I appreciate all of your help.
This script will get called and passed a customer number.
myEmailFinder "$CustID"
I want to populate a variable based on the passed in customer number.
emailAddr=$( myEmailFinder "$CustID")
I want to pull an e-mail associated with that customer number and populate a variable with it.
I would prefer this get stored in teh script and not in a separate file if possible.
Using a database is preferred, but .... per your written specification, try this
cat myEmailFinder
#!/bin/bash
case $# in 0 ) echo "usage: myEmailFinder CustID" ; exit 1 ;; esac
# given cust file like
# cust_id "\t" email_addr
fn_myEmailFinder() {
awk -F"\t" -v cust_id="$1" '{
if ($1 == cust_id) {
print $2
}
}' <<-EOF
1 user1#myCorp.com
2 user2#myCorp.com
5 user3#myCorp.com
EOF
#--^tabCh^---make sure you put a real tab char between custID and emailAddr
#tabCh-TabCh--- data indented with TabChars. EOS indented with **only** tabCh.
#send an email to cust in $1
emailAddr=$( fn_myEmailFinder "$1")
mailx -S "Test Email" "$emailAddr" <<-EOM
Here is the body of an email addressed to $emailAddr with CustID=$custID
EOM
#end of script
The block delimited by EOF is the place to store your custID and associated email Addresses. One per line, tab-delimited. The Indents on each line should be done with tab chars. The closing EOF line must be done ONLY with tab chars.
A preferable solution would be to store the "lookup table" in a separate file. That would look like
cat myEmailFinder2
#!/bin/bash
case $# in 0 ) echo "usage: myEmailFinder2 CustID" ; exit 1 ;; esac
cfgDir="/usr/local/data"
# given cust file like
# cust_id "\t" email_addr
fn_myEmailFinder() {
awk -F"\t" -v cust_id="$1" '{
if ($1 == cust_id) {
print $2
}
}' "$cfgDir"/emaillist.cfg
#send an email to cust in $1
emailAddr=$( fn_myEmailFinder "$1")
mailx -S "Test Email" "$emailAddr" <<-EOM
Here is the body of an email addressed to $emailAddr with CustID=$custID
EOM
where emaillist.cfg is laid out as above, tab-delimited.
IHTH
#!/bin/bash -
''''echo "Customer number: $1"
X=$(/bin/env python $0 $1)
echo $X
exit
'''
customers = {
42: 'customerA'
,43: 'customerB'
}
import sys
print customers.get(int(sys.argv[1]), '')
sys.exit(0)
:-|
if [ "$1" = "42" ]; then X="CustomerA" ; fi
if [ "$1" = "43" ]; then X="CustomerB" ; fi

Output a record from an existing file based on a matching condition in bash scripting

I need to be able to output a record if a condition is true.
Suppose this is the existing file,
Record_ID,Name,Last Name,Phone Number
I am trying to output record if the last name matches. I collect user input to get last name and then perform the following operation.
read last_name
cat contact_records.txt | awk -F, '{if($3=='$last_name')print "match"; else print "no match";}'
This script outputs no match for every record within contact_records.txt
Your script has two problems:
First, $last_name is not considered quoted in the context of 'awk'. For example, if "John" is to be queried, you are comparing $3 with the variable John rather than string "John". This can be fixed by adding two double-quotes as below:
read last_name
cat contact_records.txt | awk -F, '{if($3=="'$last_name'")print "match"; else print "no match";}'
Second, it actually scans the whole contact_records.txt and prints match/no match for each line of comparison. For example, contact_records.txt has 100 lines, with "John" in it. Then, querying if John is in it by this script yields 1 "match"'s and 99 "no match"'s. This might not be what you want. Here's a fix:
read last_name
if [ `cat contact_records.txt | cut -d, -f 3 | grep -c "$last_name"` -eq 0 ]; then
echo "no match"
else
echo "match"
fi

Using bash and awk to print to a specific column in a new document

I am trying to use bash and awk together with a nested for loop to print data out into columns beside each other.
so far this is what I have:
for k in {1..147..3}
do
for i in "52" "64" "60" "70" "74"
do
awk -v x="${i}" -F, 'match ($0,x) { print $k }' all.csv > final.csv
done
done
echo "script has run"
I need to print out the information into the column k in the new file.. however that does not work.
so in the csv file data is like this:
52,9/05,6109
52,9/06,6119
64,9/05,7382
64,9/06,7392
64,9/07,3382
60,9/06,3829
...
I want my output like this:
52,9/05,6109,64,9/05,7382,60,9/06,3829
52,9/06,6119,64,9/06,7392
,,,64,9/07,3382
basically, all the 52s in the first column, the 64s in fourth column, the 60s in seventh column
Instead of print $k, use printf "%s,",$k.
printf is the print formatter function that is common to many languages. %s tells it the first argument should be a string.
Note that awk won't get the $k from the shell, so you'll need to add -v k=$k.

Resources