strange issue while using FOR loop and here document inside a script - linux

In the below script the output file is missing the header record.
Some data from the PTF_LIST is also missing in the output
The same script if run with one value in the PTF_LIST
e.g PTF_LIST="LIST1" produces the header record and the data for the list in the output
The script when run with multiple values for PTT_LIST e.g PTF_LIST="LIST1 LIST2 LIST3" does not produce the desired output.The header record is missing and data for the some list values randomly does not appear in the output file.
Only a single instance of the script is run at a time.
#!/bin/ksh
OUTPUT_FILE=report_output.csv
WRKFILE=temp_ouput.tmp
# Header record.
print "column1, column2, column3" > ${OUTPUT_FILE}
PTF_LIST="LIST1 LIST2 LIST3 LIST4 LIST5 LIST6 LIST7"
for PTF_NO in $PTF_LIST
do
/usr/bin/isql -b -s',' -U$USER -P$USERPWD <<-EOT | sed -e 's/ *,/,/g' >${WRKFILE} 2>&1
use aaamaindb
go
set nocount on
set dateformat ymd
go
exec some_function #port_object='${PTF_NO}'
go
EOT
awk -F',' '{ if ( $5 == "YES" ) { print $1","$2","$3","$8","$9","$10","$11","$12","$13}}' < ${WRKFILE} >> ${OUTPUT_FILE}
done #End of for loop
thanks for your comments and answers.

Related

bash shell script transmission variable value space processing, how to space data it

bash shell script transmission variable value space processing, how to space data it
**#FileList. list.txt Delivery list belowt**
$1 $2 $3
xxxx1.com_1 Hello_2 Hello_3 - Hello
xxxx2.com_1 Hello_2 Hello_3 - Hello
get_list() {
now_list=${1} #Pass list
while read -r line; do #Circular reading
now_list_url=$(echo "${line}"|awk -F ' ' '{print $1}') #url variable1
now_list_keyword=$(echo "${line}"|awk -F ' ' '{print $2}') #keyword variable2
now_list_title=$(echo "${line}"|awk -F ' ' '{print $3}') #title variable3
#print
echo "url:${now_list_url}"
result:xxxx1.com_1
echo "keyword:${now_list_keyword}"
result:Hello_2
echo "title:${now_list_title}"
result:Hello_3 #Due to the empty grid of the transmission variable 3
result:Hello_3 - Hello #And want to be correct
done < "${now_list}"
}
#Run
get_list list.txt`
Transfer variable 3 due to space errors:Hello_3
I want correct transmission variables 3 due to space and finally the correct result:Hello_3 - Hello
#And here is because the transmission variable is incomplete,The result I finally need is the value of the value of the output complete variable 3 in the value of the complete variable3 = "Hello_3 - hello"
Because of work needs, a lot of list processing, I will save the variable value in the text
How should I deal with it
thanks
If I understand what you're trying to do, you should let read split the fields, instead of using awk:
while read -r now_list_url now_list_keyword now_list_title; do
echo "url:${now_list_url}"
# result: xxxx1.com_1
echo "keyword:${now_list_keyword}"
# result: Hello_2
echo "title:${now_list_title}"
# result: Hello_3 - Hello
done < "${now_list}"
Since three variables were given to read, it'll try to split the line into three fields. When there are more than three space-separated things in the line, all the extra gets put in the last variable. See BashFAQ #1: "How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?" for more information.

How would I use strings inside a for loop?

I apologize for my question not being specific enough but I have no choice. So I received an assignment that hasn't been completely covered in the learning material (even the person assigned to help students is having trouble helping me) since this is beyond basic bash scripting. I'm not expecting anybody to do my assignment but if I can get a clue or an idea it'll be very helpful!
My assignment:
Code a script in bash linux that will use user's input of number of rows and number of columns, and print 'hello' strong according to the user's input, like so:
For example:
User's input of number of columns:2
User's input of number of rows: 3
hello hello
hello hello
hello hello
I thought in this direction but I can't figure it out and will appreciate any help :)
echo -e 'Please enter number of rows: \n'
read rows
echo -e 'Please enter number of columns: \n'
read columns
string='hello'
for i in $columns
do
echo $string
string+=$string
done
(this is as far as I got with the first loop as what ive done here doesn't work)
Check this out:
#!/bin/bash
read -p 'Please enter number of rows and columns: ' rows columns # prompt and read both vars at once
string='hello' # set string
printf -v row "%${columns}s" # create var $row consists on N(columns) spaces
row=${row//' '/"$string "} # recreate var $row changing spaces to "$string "
printf -v col "%${rows}s" # create var $col consists on N(rows) spaces
all=${col//' '/"$row\n"} # create full set in var $all by changing spaces to "$row\n"
printf "$all" # print all
Testing:
$ ./ex
Please enter number of rows and columns: 3 5
hello hello hello hello hello
hello hello hello hello hello
hello hello hello hello hello
With two loops:
#!/bin/bash
string='hello'
read -p "x:" x
read -p "y:" y
for ((j=0; j<$y; j++)); do
for ((i=0; i<$x; i++)); do
echo -n "$space$string"
space=" "
done
space=""
echo
done
See: man bash
To read inputs you can use read builtin. For example
read -r row column
Then you can use $row and $column variables.
You'd need a nested for loop to print row x column times.
To not print newlines, use -n option of echo.
Refer help read, help for, and help echo for details. You can obviously Google these terms, too ;-)
Do yo want to golf it? :)
printf "%$((rows*columns))s" | fold -w "$columns" | sed 's/ /hello /g'
To prompt the user for rows and colums, use the read builtin:
read -p 'Enter rows: ' rows
read -p 'Enter columns: ' columns
I prefer to get my arguments on the command line.
Accordingly, one implementation (with no error checking...):
rows=$1 # first arg is rows to output
cols=$2 # second column is columns wanted
str=$3 # third arg is the string to print
while (( rows-- )) # post-decrement rows
do c=$cols # reset a column count for each new row
while (( c-- )) # post-decrement columns done
do printf "%s " "$str" # print the string with a trailing space, NO newline
done
printf "\n" # print a newline at the end of each row
done
Make sure you understand ((...)) arithmetic processing, printf, and command line argument parsing. All these are available in the documentation.
For extra credit, do proper error checking of your inputs.
If you need to read the inputs from stdin instead of the command line, replace
rows=$1 # first arg is rows to output
cols=$2 # second column is columns wanted
str=$3 # third arg is the string to print
with
read rows cols str
Better, read each with an appropriate prompt - again, details available in the manual.
Good luck.

Getting two varaibles from command output in one execution run

I'm building a script in bash for use on Linux, and I use the output of a executable to fill parameters:
version=$("${path_exec}" -version | awk '{if($1=="kernel" && $2=="release") print $3}')
patch=$("${path_exec}" -version | awk '{if($1=="patch" && $2=="number") print $3}')
This will run the executable defined in "path_exec" twice, which is time consuming. Is there a way to assign the version and path variable with a value using only one execution of "path_exec"?
An example of what I've tried to tackle this is shown below, but I don't think this will do what I want:
${path_hostexec} -version | awk '{if($1=="kernel" && $2=="release") {version_agent = $3;} else if($1=="patch" && $2=="number") {patch_agent = $3;}}'
Could you please try following. Since I didn't have output of path_exec command so couldn't test it.
myarr=($("${path_exec}" -version | awk '{if($1=="kernel" && $2=="release");val=$3} {if($1=="patch" && $2=="number") print val,$3}'))
#Now get every element in the array
for i in "${myarr[#]}"
do
echo $i
done
What I have done is:
Merged your both awk programs into one to make it run on a single time.
Now creating an array by output of awk command output(which should be val1 val2 as an example format)
Once an array created then we could get its all values by for loop or you could get its specific value by mentioning its index eg--> myarr[1] to print 2nd element.
Output both values on a single line, and let read separate the line into its two parts.
IFS=, read version patch < <($path_exec -version |
awk '/kernel release/ {v=$3}
/patch number/ {p=$3}
END {print v","p}
')
Thanks guys, I've managed to get it working thanks to your input:
version_patch_agent=$("${path_hostexec}" -version | awk '/kernel release/ {v=$3} /patch number/ {p=$3} END {print v" patch "p}')
This puts the version and patch number into a variable that I can just echo to get the info on the screen. Thanks again all!!

Create variable equal to the lines in the file, and assign the variables the value from the file sequentially

I want to create a number of variables equal to the lines in a file and assign to each of those variables a value from the file sequentially.
Say,
file1 contains device1 device2 device3 .....
file2 contains olddevice1 olddevice2 olddevice3 .....
I want values as when I do echo $A = device1
Similarly echo $B = device2 and echo $Z = device26
I tried a for loop, and even an array, but couldn't get through it.
I have tried something like below:
iin=0
var=({A..Z})
for jin in `cat file1`
do
array[$iin]="$var=$jin";
iin=$(($iin+1));
var="$(echo $var | tr '[A-Y]Z' '[B-Z]A')"
printf '%s\n' "${array[#]}"
done`
I believe you're missing the point : variables have fix names in programming languages, like $A, $B, ..., $Z: while programming you need to specify those variables inside your program, you can't expect your program to invent it's own variables.
What you are looking for, are collections, like arrays, lists, ...:
You create a collection A and you can add values to it (A[n]=value_n, or A.SetAt(n, value_n), ..., depending on the kind of collection you're using.
With bash (v4 and later) something like this mapfile code should work:
mapfile -O 1 -t array1 < file1
mapfile -O 1 -t array2 < file2
# output line #2 from both files
echo "${array1[2]}" "${array2[2]}"
# output the last line from both files
echo "${array1[-1]}" "${array2[-1]}"
Notes: mapfile just loads an array, but with a few more options.
-O 1 sets the array subscript to start at 1 rather than the default 0; this isn't necessary, but it makes the code easier to read.

Using awk to delete multiple lines using argument passed on via function

My input.csv file is semicolon separated, with the first line being a header for attributes. The first column contains customer numbers. The function is being called through a script that I activate from the terminal.
I want to delete all lines containing the customer numbers that are entered as arguments for the script. EDIT: And then export the file as a different file, while keeping the original intact.
bash deleteCustomers.sh 1 3 5
Currently only the last argument is filtered from the csv file. I understand that this is happening because the output file gets overwritten each time the loop runs, restoring all previously deleted arguments.
How can I match all the lines to be deleted, and then delete them (or print everything BUT those lines), and then output it to one file containing ALL edits?
delete_customers () {
echo "These customers will be deleted: "$#""
for i in "$#";
do
awk -F ";" -v customerNR=$i -v input="$inputFile" '($1 != customerNR) NR > 1 { print }' "input.csv" > output.csv
done
}
delete_customers "$#"
Here's some sample input (first piece of code is the first line in the csv file). In the output CSV file I want the same formatting, with the lines for some customers completely deleted.
Klantnummer;Nationaliteit;Geslacht;Title;Voornaam;MiddleInitial;Achternaam;Adres;Stad;Provincie;Provincie-voluit;Postcode;Land;Land-voluit;email;gebruikersnaam;wachtwoord;Collectief ;label;ingangsdatum;pakket;aanvullende verzekering;status;saldo;geboortedatum
1;Dutch;female;Ms.;Josanne;S;van der Rijst;Bliek 189;Hellevoetsluis;ZH;Zuid-Holland;3225 XC;NL;Netherlands;JosannevanderRijst#dayrep.com;Sourawaspen;Lae0phaxee;Klant;CZ;11-7-2010;best;tand1;verleden;-137;30-12-1995
2;Dutch;female;Mrs.;Inci;K;du Bois;Castorweg 173;Hengelo;OV;Overijssel;7557 KL;NL;Netherlands;InciduBois#gustr.com;Hisfireeness;jee0zeiChoh;Klant;CZ;30-8-2015;goed ;geen;verleden;188;1-8-1960
3;Dutch;female;Mrs.;Lusanne;G;Hijlkema;Plutostraat 198;Den Haag;ZH;Zuid-Holland;2516 AL;NL;Netherlands;LusanneHijlkema#dayrep.com;Digum1969;eiTeThun6th;Klant;Achmea;12-2-2010;best;mix;huidig;-335;9-3-1973
4;Dutch;female;Dr.;Husna;M;Hoegee;Tiendweg 89;Ameide;ZH;Zuid-Holland;4233 VW;NL;Netherlands;HusnaHoegee#fleckens.hu;Hatimon;goe5OhS4t;Klant;VGZ;9-8-2015;goed ;gezin;huidig;144;12-8-1962
5;Dutch;male;Mr.;Sieds;D;Verspeek;Willem Albert Scholtenstraat 38;Groningen;GR;Groningen;9711 XA;NL;Netherlands;SiedsVerspeek#armyspy.com;Thade1947;Taexiet9zo;Intern;CZ;17-2-2004;beter;geen;verleden;-49;12-10-1961
6;Dutch;female;Ms.;Nazmiye;R;van Spronsen;Noorderbreedte 180;Amsterdam;NH;Noord-Holland;1034 PK;NL;Netherlands;NazmiyevanSpronsen#jourrapide.com;Whinsed;Oz9ailei;Intern;VGZ;17-6-2003;beter;mix;huidig;178;8-3-1974
7;Dutch;female;Ms.;Livia;X;Breukers;Everlaan 182;Veenendaal;UT;Utrecht;3903
Try this in loop..
awk -v variable=$var '$1 != variable' input.csv
awk - to make decision based on columns
-v - to use a variable into a awk command
variable - store the value for awk to process
$var - to search for a specific string in run-time
!= - to check if not exist
input.csv - your input file
It's awk's behavior, when you use -v it can will work with variable on run-time and provide an output that doesn't contain the value you passed. This way, you get all the values that are not matching to your variable. Hope this is helpful. :)
Thanks
This bash script should work:
!/bin/bash
FILTER="!/(^"$(echo "$#" | sed -e "s/ /\|^/g")")/ {print}"
awk "$FILTER" input.csv > output.csv
The idea is to build an awk relevant FILTER and then use it.
Assuming the call parameters are: 1 2 3, the filter will be: !/(^1|^2|^3)/ {print}
!: to invert matching
^: Beginning of the line
The input data are in the input.csv file and output result will be in the output.csv file.

Resources