I just recently started using AWK and I'm still learning about it. I have solved the problem I'm about to show but I feel it's not the best solution and I'm trying to find a solution to fit within an AWK command rather than keep piping.
I have a bunch of .txt files ending for which I read the header (1st line only).
head -1 *.txt
Outputs:
==> anglia.txt <==
String - Anglian
==> carr.txt <==
String - Carr
etc..
From here I have a case switch where a user inputs 1-9. It's sorted so first line is always Anglian and second is always Carr.. etc So if a user inputs 1 I know they want to select anglian. But for further process my code I need to extract the String "Anglian".
head -1 *.txt | awk '/[a-z]/&&!/.txt/'
Outputs:
String - Anglian
String - Carr
Here I got rid of the first line that had the filename.
head -1 *.txt | awk '/[a-z]/&&!/.txt/' | awk '{print 3ドル}'
Outputs:
Anglian
Carr
Here I selected column 3 which contains the String that I need!
head -1 *.txt | awk '/[a-z]/&&!/.txt/' | awk 'NR==1{print 3ドル}'
Outputs:
Anglian
Here I selected the first row which is exactly the output that I want! However I had to use an extra pipe. All I want is a awk command that does all of this in a single command somethings around the lines of:
head -1 *.txt | awk '/[a-z]/&&/.txt/{if(NR==1)print 3ドル}'
Outputs:
EMPTY LINE
This is the problem I'm having. Since I'm having the pattern and NR in 1 command it's selecting the 1st line but the first line is a line that is being hidden by my pattern and it's the ==> anglian.txt <==
hence
head -1 *.txt | awk '/[a-z]/&&/.txt/{if(NR==2)print 3ドル}'
Outputs:
Anglian
However this is of no use because only matches Anglian where it is NR==2 and due to my case switch that I have I want it to be NR==1 otherwise the code does not work.
Is this possible? I hope I made myself clear here :)
2 Answers 2
You can replace this pipeline
head -1 *.txt | awk '/[a-z]/&&!/.txt/' | awk '{print 3ドル}'
with this one awk command
awk 'FNR == 1 {print 3ドル}' *.txt
FNR
is the file record (i.e. line) number. NR
is the cumulative record number of all records seen from all files.
Now, you can select the user's numeric choice with
awk 'FNR == 1 {print 3ドル}' *.txt | awk -v n="$user_selection" 'NR == n'
or, with a single awk:
awk -v n="$user_selection" 'FNR == 1 && ++filenum == n {print 3ドル; exit}' *.txt
If you're looking for a way to get your users to select a name from one of the files, perhaps some more advanced bash:
# read the 3rd word from the 1st line of all txt files into an array
readarray -t names < <(awk 'FNR == 1 {print 3ドル}' *.txt)
# get the user to select one of them
PS3="Choose a name: "
select name in "${names[@]}"; do
[ "$name" ] && break
done
echo "$name"
This really isn't a code review. Since you're asking "how can I do this", you should have asked on Stack Overflow.
-
\$\begingroup\$
awk -v n="$user_selection" 'FNR == 1 && ++filenum == n {print 3ドル; exit}' *.txt
worked wonders :) many thanks. Also I was in stack overflow but since I had a "solution" to the problem they told me to come here. Many thanks! \$\endgroup\$zuNEC– zuNEC2019年03月27日 16:31:43 +00:00Commented Mar 27, 2019 at 16:31
I'm afraid you can't do this like that, because NR
is a number of an input record, not a number of records matched so far. Even if it was, you need to count records matched by the first clause of the condition but actually not yet printed due to the second clause.
Probably the good way to do that is explicit counting:
BEGIN { cnt = N }
/[a-z]/&&!/.txt/ { if (cnt-- == 0) print 3ドル }
I am not sure, however, how to pass an argument from the command line to the script's variable N
.
-
\$\begingroup\$ If you do this inline instead of it's own awk script file I think you can just use Bash's variable expansion (but be sure to escape the dollar sign later in the code). Or just hard code it! \$\endgroup\$Captain Man– Captain Man2019年03月26日 20:19:18 +00:00Commented Mar 26, 2019 at 20:19
I just recently started using AWK and I'm still learning about it
Why? It was quite something when it was new. Then, there was new awk, but the world keeps turning: contemporary contenders include Perl (5+), Python (3.3+, 2.7.1 for Jython), Ruby... \$\endgroup\$head -1 *.txt
. Without that, I can't imagine why3ドル
would be printed, and I have a hard time trying to imagine the code presented works as intended. \$\endgroup\$