I'm trying to see if there is a entry in a ini-file with a user's nick as the key or not. If not; make an entry. If it exists; post a error message.
var %previous = $readini(numbers.ini,Number,$nick)
if(%previous != $null) {
msg $chan $nick , you have already written %previous .
}
else {
writeini numbers.ini Number $nick $2
msg $chan $nick has written $2.
}
What's happening with the script above is that it is never $null, and I can't find anywhere what is returned from $readini if a key is not found.
$ini(numbers.ini, Numbers, $nick) will return number N (indicating that the item is the Nth item in that section) if it exists. If it does not exist, it will return $null.
In your case, you'll want something along the lines of
if ($ini(numbers.ini, Numbers, $nick) != $null) {
msg $chan $nick , you have already written $readini(numbers.ini, Numbers, $nick)
}
else {
writeini numbers.ini Numbers $nick $2
msg $chan $nick has written $2.
}
Related
I am recieving a syntax error on "else" for this shell:
{for (i=8;i<=NF;i+=3)
{if ($0~"=>") # if-else statement designed to flag file / directory transfers
print "=> flag,"$1"," $2","$3","$4 ","$5","$6","$7"," $(i)","$(i+1)","$(i+2);
{split ($(i+2), array, "/");
for (x in array)
{j++;
a[j] =j;
printf (array[x] ",");}
printf ("%s\n", "");}
else
print "no => flag,"$1"," $2","$3","$4 ","$5","$6","$7"," $(i)","$(i+1)","$(i+2)
}
}
Can't figure out why. If I delete the array block (starting with split()), all is well. But I need to scan the contents of $(i+2), so cutting it does me no good.
Also, if anyone has guidance on a good list of how to interpret error messages, that would be great.
Thanks for your advice.
EDIT: here is the above script laid out with sensible formatting:
{
for (i=8;i<=NF;i+=3) {
if ($0~"=>") # if-else statement designed to flag file / directory transfers
print "=> flag,"$1"," $2","$3","$4 ","$5","$6","$7"," $(i)","$(i+1)","$(i+2);
{
split ($(i+2), array, "/");
for (x in array) {
j++;
a[j] =j;
printf (array[x] ",");
}
printf ("%s\n", "");
}
else
print "no => flag,"$1"," $2","$3","$4 ","$5","$6","$7"," $(i)","$(i+1)","$(i+2)
}
}
First thing first, since you didn't post any samples of input and expected output so didn't test it at all. Could you please try following, I hope you are running this in .awk script style. Also these are mostly syntax/cosmetic changes NOT on logic part, since no background was given on problem.
BEGIN{
OFS=","
}
{
for (i=8;i<=NF;i+=3){
if ($0~/=>/){
print "=> flag,"$1,$2,$3,$4,$5,$6,$7,$(i),$(i+1),$(i+2)
split ($(i+2), array, "/");
for(x in array){
j++;
a[j] =j;
printf (array[x] ",")
}
printf ("%s\n", "")
}
else{
print "no => flag",$1,$2,$3,$4,$5,$6,$7,$(i),$(i+1),$(i+2)
}
}
}
Problems fixed in OP's attempt:
{ starting curly braces(which indicates that if condition of for loop with multiple statements is started) could be in last of the line where they are present, NOT in next line, for better visibility purposes, I fixed in for loop and if condition first.
Since you are using regexp matching with a pattern so I fixed from $0~"=>" TO $0~/=>/.
Added BEGIN section in your attempt where I have set OFS(output field separator) value to , so that you need NOT to print like "," to print comma between variables, just , between variables will do the trick.
Fixed indentation, so that we are NOT confused where to close loop/condition and where to NOT.
I am struggling with resetting some awk variables. I have multiple lines of the form:
one two three ... ten
with various appearances of each word in every line. I am trying to count the number of times each word is one each line, separate from the counts from the other lines.
this is what I have so far:
{ for(i=length(Num); i>0; i--)
if( Num[i] == "one" )
{
oneCount++
}
else if( Num[i] == "two" )
{
twoCount++
}
else if( Num[i] == "three" )
{
threeCount++
}
...
}
when I print out the count values, the count doesn't reinitialize with each new line. how do i fix this?
any help is much appreciated
You seem very confused. To get a count of each field in a ;-separated line would be:
awk -F';' '{
split("",cnt) # or "delete cnt" if using GNU awk.
for (i=1;i<=NF;i++) {
cnt[$i]++
}
for (word in cnt) {
print word, cnt[word]
}
}' file
Now is there anything else you need it to do?
Try initializing an array in the BEGIN portion to however many variables you'd like to count. You can run a loop in the portion to clear the array at the beginning of every new line.
Alternatively, you could just reset the value of each variable to 0 or null in the portion of the program that executes every line, but I'm guessing you have many variables.
Brand new to mSL and just playing around with trying to make a bot.
So I am trying to make something that when a user says a certain word, they get +1 to a count against their name. However they can then not say the word again to further increase their count unlimited times, they must find a new word.
To ensure the words cannot be used multiple times I am writing the words to a file, I then need to load these words and check if its been said already or not against what the user has just said, and act appropriately
on *:TEXT:&:#:{
var %msg
if ($1 == text1) { %msg = msg1 }
elseif ($1 == text2) { %msg = msg2 }
elseif ($1 == text3) { %msg = msg3 }
else { return }
msg # %msg
var %keyword = $readini(keyword.ini,#,$nick)
if (%keyword == $1) {
msg # you already have this keyword! :(
}
else {
var %count = $readini(cookies.ini,#,$nick)
inc %count
writeini cookies.ini # $nick %count
writeini keyword.ini # $nick %keyword $+ , $+ $1
}
}
keyword.ini file looks like:
nickname=text1,text2
is there anyway in mSL that I can grab the list (already done in code above) and then use something similar to .split(,) to divide up the words to run through a for/next?
Thanks in advance
EDIT:
I tried out the below and although it did work! I then deleted the file to test it out, and it never remade the file despite the writeini. I even added a writeini keyword.ini at the start of the script to make sure the file is present before any text is written, still didn't make it.
on *:TEXT:&:#:{
var %msg
if ($1 == text1) { %msg = msg1 }
elseif ($1 == text2) { %msg = msg2 }
elseif ($1 == text3) { %msg = msg3 }
else { return }
msg # %msg
var %i = 1, %keyword = $readini(keyword.ini,n,$chan,$nick), %cookie = $readini(cookies.ini,n,#,$nick)
while (%i <= $numtok(%keyword, 44)) {
if ($istok(%keyword, $1, 44)) {
msg # you already have this keyword! :(
}
else {
inc %cookie
writeini cookies.ini $chan $nick %cookie
msg # congrats! you found a keywords
writeini keyword.ini $chan $nick $addtok(%keyword, $1, 44)
}
inc %i
}
You're looking for mIRC's token identifiers. I would suggest reading the help files (/help token identifiers) to read more about them.
Use $istok() to check whether the line contains that keyword already:
if ($istok(%keyword, $1, 44)) // Keyword exists
Use $addtok() to add a new keyword to the line, and then write it to the file:
writeini keyword.ini # $nick $addtok(%keyword, $1, 44)
Use $numtok() and $gettok() to create a loop to read all the values:
var %i = 1, %keywords = $readini(cookies.ini, n, channel, nick)
while (%i <= $numtok(%keywords, 44)) {
echo -a Keyword %i $+ : $gettok(%keywords, %i, 44)
inc %i
}
Important note: always use the n switch with $readini() (like I did above) when reading data, especially when it's data that users can enter. Without it, $readini() will evaluate the contents (e.g., $me will be evaluated to your current nickname). Users can inject malicious code this way.
Edit for the inserted question: You are using a while loop to check whether they possess the cookie - it will loop once for every cookie they have (0 loops for no cookies). You don't need this while loop at all, since $istok(%keywords $1, 44) will take all the keywords and return $true if $1 is in that list of tokens.
Just the following will suffice:
var %keywords = $readini(keyword.ini,n,$chan,$nick), %cookie = $readini(cookies.ini,n,#,$nick)
if ($istok(%keywords, $1, 44)) {
; the token $1 is in the list of tokens %keywords
msg # you already have this cookie! :(
}
else {
; the token $1 did not appear in the list of tokens %keywords
inc %cookie
writeini cookies.ini $chan $nick %cookie
writeini keyword.ini $chan $nick $addtok(%keywords, $1, 44)
}
I've this error:
Use of uninitialized value in concatenation (.) or string at...
This is my code:
$queryH= $dbh->prepare($query);
$queryH->execute();
my $i=0;
my $result;
while (#data = $queryH->fetchrow_array())
{
$result=$data[$i];
if ($result)
{
print "$result \n";
}
else
{
print "Records Not Found!\n";
last;
}
print "\n";
$i++;
}
print "\n\n";
$queryH->finish();
$dbh->disconnect();
What error is there in my code?
The error is on the line:
$result=$data[$i];
You are starting out with $i=0 and you increment it with each pass of the while loop. You look at $data[$i] once for each line of database result. So for the first row, you look at $data[0]. For the second row of data, you look at $data[1] and so on. At some point, your $i (which is effectively a rowcount starting at zero) will be higher than the number of fields per row. That produces the error message.
If you put in a print "$i\n" in the beginning of the while block you will see what I am talking about.
the script was working. I added some comments and renamed it then submitted it. today my instructor told me it doesnt work and give me the error of awk 1 unexpected character '.'
the script is supposed to read a name in command line and return the student information for the name back.
right now I checked it and surprisingly it gives me the error.
I should run it by the command like this:
scriptName -v name="aname" -f filename
what is this problem and which part of my code make it?
#!/usr/bin/awk
BEGIN{
tmp=name;
nameIsValid;
if (name && tolower(name) eq ~/^[a-z]+$/ )
{
inputName=tolower(name)
nameIsValid++;
}
else
{
print "you have not entered the student name"
printf "Enter the student's name: "
getline inputName < "-"
tmp=inputName;
if (tolower(inputName) eq ~/^[a-z]+$/)
{
tmpName=inputName
nameIsValid++
}
else
{
print "Enter a valid name!"
exit
}
}
inputName=tolower(inputName)
FS=":"
}
{
if($1=="Student Number")
{
split ($0,header,FS)
}
if ($1 ~/^[0-9]+$/ && length($1)==8)
{
split($2,names," ")
if (tolower(names[1]) == inputName || tolower(names[2])==inputName )
{
counter++
for (i=1;i<=NF;i++)
{
printf"%s:%s ",header[i], $i
}
printf "\n"
}
}
}
END{
if (counter == 0 && nameIsValid)
{
printf "There is no record for the %-10s\n" , tmp
}
}
Here are the steps to fix the script:
Get rid of all those spurious NULL statements (trailing semi-colons at the end of lines).
Get rid of the unset variable eq (it is NOT an equality operator!) from all of your comparions.
Cleanup the indenting.
Get rid of that first non-functional nameIsValid; statement.
Change printf "\n" to the simpler print "".
Get rid of the useless ,FS arg to split().
Change name && tolower(name) ~ /^[a-z]+$/ to just the second part of that condition since if that matches then of course name is populated.
Get rid of all of those tolower()s and use character classes instead of explicit a-z ranges.
Get rid of the tmp variable.
Simplify your BEGIN logic.
Get rid of the unnecessary nameIsValid variable completely.
Make the awk body a bit more awk-like
And here's the result (untested since no sample input/output posted):
BEGIN {
if (name !~ /^[[:alpha:]]+$/ ) {
print "you have not entered the student name"
printf "Enter the student's name: "
getline name < "-"
}
if (name ~ /^[[:alpha:]]+$/) {
inputName=tolower(name)
FS=":"
}
else {
print "Enter a valid name!"
exit
}
}
$1=="Student Number" { split ($0,header) }
$1 ~ /^[[:digit:]]+$/ && length($1)==8 {
split(tolower($2),names," ")
if (names[1]==inputName || names[2]==inputName ) {
counter++
for (i=1;i<=NF;i++) {
printf "%s:%s ",header[i], $i
}
print ""
}
}
}
END {
if (counter == 0 && inputName) {
printf "There is no record for the %-10s\n" , name
}
}
I changed the shebang line to:
#!/usr/bin/awk -f
and then in command line didnt use -f. It is working now
Run the script in the following way:
awk -f script_name.awk input_file.txt
This seems to suppress the warnings and errors.
In my case, the problem was resetting the IFS variable to be IFS="," as suggested in this answer for splitting string into an array. So I resetted the IFS variable and got my code to work.
IFS=', '
read -r -a array <<< "$string"
IFS=' ' # reset IFS