Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Help converting Perl Script to Awk script 1

Status
Not open for further replies.

JanneJannesson

Technical User
Apr 29, 2019
4
SE
Hello guys, I could really use some help. I'm trying to learn AWK but it wasn't at all as easy as I thought it would be. I have a really simple Perl script, that prints a specified text file, as well as the line number next to it. The only difference I would like to make, is that I specify the file as an argument at the command line instead of the program asking me for it. How would I go about doing this and making an AWK script? Here's my Perl script:
Code:
 #!/usr/local/bin/perl
    use warnings;
    use strict;

    print "Specify the file you want to look at:\n";
    my $file_name = <STDIN>;
    chomp $file_name;

    open(FH, '<', $file_name) or die "Cannot open $file_name: $!";
    print "This is the listed content of: $file_name\n";

    my $line_n = 1;
    while(<FH>){
    print "$line_n. $_";
    $line_n++;
}

    close(FH);
Sorry if I'm breaking any forum rules, this is my first post. Any advice or tips is greatly appreciated. Thanks in advance.
 
Hi

Code:
awk '$0=NR". "$0' /path/to/file

BTW, the above is the equivalent of this :
Code:
perl -pe '$_="$.. $_"' /path/to/file

BTW, if the dot after the number is not mandatory, see whether you like this more :
Code:
cat -n /path/to/file

JanneJannesson said:
Sorry if I'm breaking any forum rules, this is my first post.
Not really breaking rules, but Thread Type should be
question.png
Question, not
lightbulb.png
Helpful Tip. ( You can not change it yourself, but if you click the
redflag.png
Report link at the bottom of your post, then you can ask forum management to change it. )
And we used to write pieces of code between [tt][ignore]
Code:
[/ignore][/tt] and [tt][ignore]
[/ignore][/tt] TGML tags to improve readability.

Feherke.
feherke.github.io
 
Hi, thank you for your response, I flagged my own post as well as added the code tags.

I tried your first bit of code, and it worked great in the command line. However --
Perhaps I was unclear in my original post, what would the awk script equivalent be to your first row of code?
feherke said:
Code:
awk '$0=NR". "$0' /path/to/file
I want to be able to run the script from the command line like so(or something similar):
Code:
awk 'test.awk' test.txt

Hope this made things clearer, if not tell me and I'll try and clear things up.
 
Hi

Not exactly like that, [tt]awk[/tt] expects the 1[sup]st[/sup] parameter to be code. So if you pass it a script file name instead, then you have to tell it :
Code:
awk -f test.awk test.txt
In which case the content of test.awk is only what we passed earlier in the command line :
Code:
$0=NR". "$0

Alternatively ( assuming you are on a Unix or Unix-like operating system ) you could set execute permission on the test.awk file and use it like this :
Code:
./test.awk test.txt
In which case the content of test.awk has to contain a shebang ( user the actual path to [tt]awk[/tt] on your system ) too :
Code:
#!/usr/bin/awk -f
$0=NR". "$0


Feherke.
feherke.github.io
 
Hello!
Thank you for your quick response! This is exactly what i was seeking. AWK seems to be really handy once you get used to it. Literally one row of code instead of 10 in Perl.
You really cleared up a few things for me, including how to actually run the AWK script, I read somewhere that single quotes: ' were necessary. For some reason I also thought I needed to use the BEGIN and END command, which obviously I didn't need to. So simple. Thank you, once again.
 
But why reinvent the wheel. the cat processor was written to dump a file to the screen

cat -n /path/to/file

Bill
Lead Application Developer
New York State, USA
 
Why not? The actual purpose of this wasn't for the scripts sake, it was to try and get a basic understanding of awk.
 
true

Bill
Lead Application Developer
New York State, USA
 
Hi

JanneJannesson said:
The actual purpose of this wasn't for the scripts sake, it was to try and get a basic understanding of awk.
Then I am afraid my answer was not that helpful. :-( Let me try to explain.

Awk code is built from [tt]pattern { action statements }[/tt] pairs, where action statements get executed only if the pattern evaluates to true. With the exception of some special patterns all such [tt]pattern { action statements }[/tt] pairs get executed for each input record.

Both pattern and action statements can be left out ( but not in the same time ), in which case their default are used :[ul]
[li]default pattern is 1, which being a logical true, means always[/li]
[li]default action statements is {print}, which being equivalent with {print $0} prints out the current record[/li]
[/ul]
Code:
[navy]$0[/navy] [teal]=[/teal] NR [i][green]". "[/green][/i] [navy]$0[/navy]
[gray]# actually means :[/gray]
[navy]$0[/navy] [teal]=[/teal] NR [i][green]". "[/green][/i] [navy]$0[/navy] [teal]{[/teal] [b]print[/b] [teal]}[/teal]

[gray]# alternatively we can put our code in the action part and use no pattern :[/gray]
[teal]{[/teal] [b]print[/b] NR [i][green]". "[/green][/i] [navy]$0[/navy] [teal]}[/teal]
( As we set the current record ( [tt]$0[/tt] ) to current record number ( [tt]NR[/tt] ) concatenated with a piece of string and the current record, the result can never be false, so will always be printed. )

Here is a close rewrite of your original Perl code :
Code:
[gray]#!/usr/bin/awk -f[/gray]

[b]BEGIN[/b] [teal]{[/teal]
    [b]print[/b] [i][green]"Specify the file you want to look at:"[/green][/i]
    [b]getline[/b] file_name

    [b]print[/b] [i][green]"This is the listed content of: "[/green][/i] file_name

    line_n [teal]=[/teal] [purple]1[/purple]
    [b]while[/b] [teal]([/teal]success [teal]=[/teal] [b]getline[/b] [teal]<[/teal] file_name[teal]) {[/teal]
        [b]if[/b] [teal]([/teal]success [teal]==[/teal] -[purple]1[/purple][teal]) {[/teal]
            [b]print[/b] [i][green]"Cannot open "[/green][/i] file_name [i][green]": "[/green][/i] ERRNO [teal]>[/teal] [i][green]"/dev/stderr"[/green][/i]
            [b]exit[/b] [purple]1[/purple]
        [teal]}[/teal]

        [b]print[/b] line_n [i][green]". "[/green][/i] [navy]$0[/navy]
        line_n[teal]++[/teal]
    [teal]}[/teal]

    [b]close[/b][teal]([/teal]file_name[teal])[/teal]
[teal]}[/teal]
Some explanations :[ul]
[li]The [tt]BEGIN[/tt] is a special pattern, means the action gets executed before processing the input file. As in this version there is no input file specified as command line parameter, there will be no automatic input processing. So we must use [tt]BEGIN[/tt] to have our code executed.[/li]
[li]There is no explicit file opening. The file gets opened when reading from it for the 1[sup]st[/sup] time. So we can do the error checking only after the [tt]getline[/tt] call.[/li]
[li]There is no [tt]die[/tt], the closes equivalent is to [tt]print[/tt] to stderr then to [tt]exit[/tt] with a non-zero exit code[/li]
[/ul]

Feherke.
feherke.github.io
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top