Questions related to if in awk context and if without awk context


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Questions related to if in awk context and if without awk context
# 8  
Old 01-31-2019
Quote:
Originally Posted by Don Cragun
I explained the reasons why the awk code you supplied won't work. You can choose to ignore my comments and continue to wonder why your code doesn't work. Trying to use shell variables in awk and assume that shell variable expansions will work in awk will never work the way you have used them because awk is not bash.


Uh, my awk code works fine provided $input is a file in the working directory. I am not using any special editors, and after reading RudiC's comments, I restarted my system and went to a real terminal (not terminal emulator) and did the following at a prompt:





AfileinDir is simply a file with some data in a couple of fields.



Code:
 
 
    input=”AfileinDir” 



    awk '{if($input == $(ls)) {print $1 "\t" $2;} }' $input

code works fine. Go to a directory on your computer, define input as a file in that directory that has at least 2 fields and copy paste the awk line above.


My first question relates to the else portion of the code which I haven't included. I know * that * part doesn't work, which is why I asked for help on improving the script.


My second question is still not being answered because so far the respondents are saying my code doesn't work when it does?? No special emulators. Straight from tty1 terminal.
p { margin-bottom: 0.1in; line-height: 115%; }
# 9  
Old 01-31-2019
Quote:
Originally Posted by Seth
Uh, my awk code works fine provided $input is a file in the working directory. I am not using any special editors, and after reading RudiC's comments, I restarted my system and went to a real terminal (not terminal emulator) and did the following at a prompt:





AfileinDir is simply a file with some data in a couple of fields.



Code:
 
 
    input=”AfileinDir” 



    awk '{if($input == $(ls)) {print $1 "\t" $2;} }' $input

code works fine. Go to a directory on your computer, define input as a file in that directory that has at least 2 fields and copy paste the awk line above.


My first question relates to the else portion of the code which I haven't included. I know * that * part doesn't work, which is why I asked for help on improving the script.


My second question is still not being answered because so far the respondents are saying my code doesn't work when it does?? No special emulators. Straight from tty1 terminal.
p { margin-bottom: 0.1in; line-height: 115%; }
Please explain in English what you think the expression in the if statement in:
Code:
awk '{if($input == $(ls)) {print $1 "\t" $2;} }

is doing. Since you can't get the else clause to work, by definition, your code is not working. How can you say your code is working when it won't run if the filename you pass to it is not a file that exists in the current directory? Furthermore, it is my belief that what the code above is doing is not doing what you think it is. Whether or not that means it is working when the named file does exist is open for discussion. I claim that if it is not doing what you think it is doing, it is not working. You claim that since the then clause of your if statement is working, everything is fine.

Without running the following code, what output do you think it would produce:
Code:
awk '{if($input == $(ls)) {print $1 "\t" $2 "\t$input=\"" $input "\"\t$(ls)=\"" $(ls) "\"";} } $input

After you have decided what output you think it should produce, run it and compare the output you get to the output you thought it should produce. Then go back and look at how I said that expression in the if statement would be evaluated in my comments in post #4 in this thread.

Please run the above test and let us know what happens!

As I said before, I can't test your code using the version of awk that I have available on my system because the code you're using is not technically correct (and produces a syntax error in the version of awk that I'm using, but runs without producing a syntax error in the version of awk that you're using). I can force the version of awk I'm using to get the results you're seeing by changing your code to:
Code:
awk '{if($input == $(ls+0)) {print $1 "\t" $2;} }

# 10  
Old 01-31-2019
Quote:
Originally Posted by Don Cragun
Please explain in English what you think the expression in the if statement in:
Code:
awk '{if($input == $(ls)) {print $1 "\t" $2;} }

is doing. Since you can't get the else clause to work, by definition, your code is not working. How can you say your code is working when it won't run if the filename you pass to it is not a file that exists in the current directory? Furthermore, it is my belief that what the code above is doing is not doing what you think it is. Whether or not that means it is working when the named file does exist is open for discussion. I claim that if it is not doing what you think it is doing, it is not working. You claim that since the then clause of your if statement is working, everything is fine.

Never said the else clause was working, that's why I asked for a different way to script it.


First, the code will return an error, since the code you provided doesn't close the awk command nor does it provide it a file to look at.


But if those were present, and in English:


awk will first examine the file to see if it's present. Then it will evaluate the value of variable input to see if it is equal to the value of what a list (ls) command returns. ‘ls' will return every non hidden file in the directory it's run in, so strictly speaking, all the strings returned taken as a whole will not equal the value of input - but this is done in the context of an awk command with a specific file (the value of input) to look at, and if true (the file is present) it will print out the first field, followed by a tab, followed by the second field.


If, however, the value of input is not in the directory (the file isn't listed), then awk will exit with an error. That error is
Code:
awk: fatal: cannot open file `a' for reading (No such file or directory)

where ‘a' is not a file in the directory. This is the reason why else is never executed - because the error is returned before the condition and commands that form part of the if statement are ever read.
p { margin-bottom: 0.1in; line-height: 115%; }


Quote:
Originally Posted by Don Cragun
Without running the following code, what output do you think it would produce:
Code:
awk '{if($input == $(ls)) {print $1 "\t" $2 "\t$input=\"" $input "\"\t$(ls)=\"" $(ls) "\"";} } $input

After you have decided what output you think it should produce, run it and compare the output you get to the output you thought it should produce. Then go back and look at how I said that expression in the if statement would be evaluated in my comments in post #4 in this thread.

Please run the above test and let us know what happens!

it will return a prompt because you didn't close off the awk command before providing the file




with the awk command closed off,
Sorry, I had to run it to see what the code was doing Smilie. But you're changing the value of both $input and $(ls) so it's going to list the values of those as you specified.I don't see how this helps me with either of my questions in the original post.

p { margin-bottom: 0.1in; line-height: 115%; }




Quote:
Originally Posted by Don Cragun
As I said before, I can't test your code using the version of awk that I have available on my system because the code you're using is not technically correct (and produces a syntax error in the version of awk that I'm using, but runs without producing a syntax error in the version of awk that you're using). I can force the version of awk I'm using to get the results you're seeing by changing your code to:
Code:
awk '{if($input == $(ls+0)) {print $1 "\t" $2;} }


Code:
 awk --version
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)
Copyright (C) 1989, 1991-2016 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

# 11  
Old 02-01-2019
I sincerely apologize for not being able to test the code I suggested you try on the system I'm using (and, therefore, missing a closing single-quote in the code I provided).

I'm sorry that you believe that I should be required to download all of the software you're using on your system onto my system in order to try to help you understand the code you're using. I AM NOT GOING TO DO THAT! I am perfectly happy with the way awk works on my system even though awk on your system has some (non-standard) extensions that do some nice things in some cases. What those extensions do has nothing to do with what you're doing nor with what you're trying to do. The difference we are seeing is because you are doing something that the standards describe as producing "unspecified behavior" and your version of awk produces a different unspecified behavior than my version of awk produces.

All that I was trying to do with the awk statement I was trying to get you to run was to show that the value of $input and the value of $(ls) inside your awk script have absolutely no relationship to the value of $input or the value of $(ls) in bash outside of your awk script.

Nothing in your explanation in English of what the expression in your awk if statement is true. The awk variable input is not defined anywhere in your awk code (only the shell variable input is defined; not the awk variable input). In bash $(ls) is a command substitution that runs the ls command and substitutes the output it produces. In awk $(ls) is a command that expands to the contents of the field number specified by the value of the awk ls variable converted to an integer. The awk and shell == operators are a request to compare the two operands on both sides of that operator. If there is more than one file in a directory and one of those files is the name of the file you're processing, there is absolutely no way that the name of that one file can possibly be equal to the list of names of files that are present in that directory. Since you are seeing the output you're seeing, your version of awk has to be expanding both sides of the comparison to the expansion of $0 which (in awk) is the entire contents of the current input line.

With the missing quote added AND assuming that you had already defined the shell variable input as you had shown before AND assuming that the file named AfileinDir contained the two input lines:
Code:
Line 1 in file AfileinDir
AfileinDir's 2nd line

I would expect the sequence of commands:
Code:
input="AfileinDir"
awk '{if($input == $(ls)) {print $1 "\t" $2 "\t$input=\"" $input "\"\t$(ls)=\"" $(ls) "\"";} }' "$input"

to produce output very similar to the following:
Code:
Line	1	$input="Line 1 in file AfileinDir"	$(ls)="Line 1 in file AfileinDir"
AfileinDir's	2nd	$input="AfileinDir's 2nd line"	$(ls)="AfileinDir's 2nd line"

Despite what you said, absolutely nothing in the code above assigns any value to the awk variables input and ls; that code only displays the values that the expression in your awk if statement expression are comparing (i.e., the entire contents of the current line in AfileinDir on both sides of the ==).

Maybe if we rewrite that as:
Code:
input="AfileinDir"
awk '{if($input == $(ls)) {print $1 "\t" $2;print $input;print $(ls); print "End of record #" NR;} }' "$input"

which (if you set the contents of the file named AfileinDir to the contents I specified above), I expect will produce the output:
Code:
Line	1
Line 1 in file AfileinDir
Line 1 in file AfileinDir
End of record #1
AfileinDir's	2nd
AfileinDir's 2nd line
AfileinDir's 2nd line
End of record #2

you will see that $input and $(ls) in your awk script do not expand to the strings you think they will expand to.

I know that you don't want to just use the shell (i.e. bash) to determine whether or not the variable read from your script's user (i.e. input) is the name of a file in your current directory, but that is exactly what the simple bash command:
Code:
if [ -f "$input" ]
then	# The name of an existing regular file was given.  Print the first two fields.
	while read -r field1 field2 rest
	do	printf '%s\t%s\n' "$field1" "$field2"
	done < "$input"
else	# The name given does not name an existing file.
	echo "file \"$input\" not in this Directory"
	exit 1
fi

that I suggested in post #4 did for you. If the shell variable input contains the name of a regular file that exists in the current directory, it will perform the while loop in the then clause of the if statement. Otherwise, it will print the name of the file the user supplied and say that that file is not in this Directory and then exit with a non-zero exit status as specified in the else clause of the if statement.
This User Gave Thanks to Don Cragun For This Post:
# 12  
Old 02-01-2019
Quote:
Originally Posted by Seth
Uh, my awk code works fine provided $input is a file in the working directory. ...
Quote:
Never said the else clause was working,
I'm not as eloquent in the English language as Don Cragun is, nor am I as patient. And, I hope you believe me really wanting to help you.
That said: He's right, and you are wrong.
Your code does NOT "work fine". It may by sheer accident provide an answer that suits you, but I'm sure that's not what you want.

For the if clause in question, replace it with
Code:
if (A == A) print ...

or, even better,
Code:
if (1) print ...

and see what you get, mayhap even trying the else clause. You may also want to closely read and understand all the posts in your thread.
Then come back, and we'll continue the discussion.
This User Gave Thanks to RudiC For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Context for use of [.symbol.] awk notation

Hi Just wondering ... do you have an example of context that would demonstrates how usefull the awk notation can efficiently be used ? Thx :rolleyes: (6 Replies)
Discussion started by: ctsgnb
6 Replies

2. UNIX for Advanced & Expert Users

Interupt Context Switching

If suppose a middle level interrupt is being serviced and a high priority interrupts comes in then in that case what all process will take place. The interrupt context switch will happen. But where will the interrupt context be saved? Is there something called as part process data area? (4 Replies)
Discussion started by: rupeshkp728
4 Replies

3. Linux

involuntary context switching

In a kernel based on 2.6.27: In the schedule() routine they have a local variable switch_count: /* * schedule() is the main scheduler function. */ asmlinkage void __sched schedule(void) { struct task_struct *prev, *next; unsigned long *switch_count; struct rq... (2 Replies)
Discussion started by: chriskot
2 Replies

4. Slackware

Context dependent symlinks

Ive got multiple PCs, sharing an NFS mounted home dir. For certain apps I would like to keep the config files host specific. Easy solution is to create symlinks to local folders for configs. Ideally I would still want the .config files to reside in the user home folder. Is it possible to... (2 Replies)
Discussion started by: agentrnge
2 Replies

5. UNIX for Dummies Questions & Answers

Context-switching question

Hi all, I've got this question that i need to solve: "Type `vmstat -s; vmstat -n 1 5; vmstat -n 1 5; vmstat -s` to your Ruby interpreter. Then terminate your Ruby session. Run the Unix com- mand vmstat -s; vmstat -n 1 5; vmstat -s in the same terminal window you had been using for Ruby. Did... (1 Reply)
Discussion started by: snowboarder
1 Replies

6. UNIX for Dummies Questions & Answers

Split based on Context

Hello, I have a file that I want to be able to split at specific positions. For example in the file below I want to be able to split at every occurence of 2 at the start of a line, into multiple files. 2 abc PQRST abcRSTG 2 cde FGKL abcLKGRG ABCLKgrg 2 lmn OPT lmopqrst uvwxyz ... (1 Reply)
Discussion started by: Gussifinknottle
1 Replies

7. Shell Programming and Scripting

grep help after context

Hi, There's a file with below contents which I have to read based on the input parameter provided by the user. FILE_ID=1 FILE_FTP_ID=ftp.server1.com FILE_FTP_USER=user1 FILE_FTP_PASS=pass1 FILE_ID=2 FILE_FTP_ID=ftp.server2.com FILE_FTP_USER=user2 FILE_FTP_PASS=pass2 FILE_ID=3... (6 Replies)
Discussion started by: dips_ag
6 Replies

8. UNIX for Advanced & Expert Users

context lost problem

there are several same servers(process) on more than one server(machine) providing the same service. we store session/context within the server(process), if the same client login, he will be directed to the very server service for him last time. But, if a server(machine or process) down, the... (1 Reply)
Discussion started by: zhongyj
1 Replies

9. Shell Programming and Scripting

keep context in awk

here is a data file. ------------------------------------- KSH, CSH, BASH, PERL, PHP, SED, AWK KSH, CSH, BASH, PERL, PHP, BASH, PERL, PHP, SED, AWK CSH, BASH, PERL, PHP, SED, KSH, CSH, BASH, PERL, PHP, SED, AWK ------------------------------------- My desired output is... (2 Replies)
Discussion started by: VTAWKVT
2 Replies

10. UNIX for Advanced & Expert Users

Context Switching

I know that this is a relative question but can someone give me an idea of what would be considered a high number of context switches? I am running vmstat and show a cs value of between 5000 and 6000 on a 4 processor system. How can I deduce if this number is high or not? Also, the timeslice... (2 Replies)
Discussion started by: keelba
2 Replies
Login or Register to Ask a Question