Showing posts with label chatGPT. Show all posts
Showing posts with label chatGPT. Show all posts

Tuesday, July 25, 2023

Using chatGPT to clean up Perl programs on a Linux server (a developing tutorial) using sed and awk

Introduction


When my University decided to upgrade its RedHat server which hosted my teaching material, I expected that this would be a smooth process. I was wrong.
Every Perl script on my sites failed.
The problem had to do with the @INC variable, which tells Perl where modules with the extensiom ".pm" (in my case) reside. The Perl documentation tells us:
Prior to Perl 5.26, . -which represents the current directory, 
was included in @INC; it has been removed. This change in behavior is 
documented in PERL_USE_UNSAFE_INC and it is not recommended that . 
be re-added to @INC. If you need to modify @INC at runtime, 
you should use the use lib pragma to get the machine-dependent 
library properly loaded as well:

use lib '/mypath/libdir/';
use SomeMod;

This seems to imply that I need to change every perl script on this server to include a 'use lib' statement. There are several hundred programs involved. That means we have to use the 'sed' unix utility, a stream editor. But my expertise is limited in sed, and programming it would drive me mad. Hello chatGPT.

My first chatGPT attempt


I wrote: "Write a sed script to insert a line of code above the first instance of the word "use"." in the chatGPT QUERY BOX. It answered:

#!/bin/sed -f

# Add a line of code above the first instance of "use"
/\<use\>/ {
    i\
    # Line of code to insert
}
 Yes, hold on hold on
# Print all lines
1,$ p

with the accompanying text: "To use this script, save it to a file (e.g., 'insert_code.sed'), make it executable ('chmod +x insert_code.sed'), and then run it with 'sed -f insert_code.sed input_file'. Replace 'input_file' with the path to the file you want to modify. Make sure to replace '# Line of code to insert' with the actual code you want to insert. The code should be written in a way that sed can understand it (e.g., escape special characters with a backslash if necessary). The script searches for the first occurrence of the word "use" (separated by word boundaries) and inserts the line of code above it. All other lines are printed unchanged." k

Before rushing in

We will make a safety subfolder containing some test cases and the sed file, test everything there, and then apply the sed program to the contents of the cgi-bin directory which is serving the web. This is the line we have to add: use lib '/home/chem12x/public_html/cgi-bin';

First steps


we start by creating a sub-directory called 'test'

  chem12x@chemphys cgi-bin]$ mkdir test

Next, we copy some code from cgi-bin to cgi-bin/test:

  cp ../sop*.pl .

Then we check that what we did was OK:

 ls 

with output:
  


-rwxr-xr-x. 1 chem12x chem12x  13K Jul 15 19:30 sophiakp1a.pl*
-rwxr-xr-x. 1 chem12x chem12x  15K Jul 15 19:30 sophiakp1.pl*
-rwxr-xr-x. 1 chem12x chem12x  12K Jul 15 19:30 sophiakp1popup.pl*
-rw-r--r--. 1 chem12x chem12x 6.7K Jul 15 19:30 sophiaKp1_PSGI.pl
-rwxr-xr-x. 1 chem12x chem12x  11K Jul 15 19:30 sophiakp1safety2.pl*
-rwxr-xr-x. 1 chem12x chem12x 9.8K Jul 15 19:30 sophiakp1safety3.pl*
-rwxr-xr-x. 1 chem12x chem12x  11K Jul 15 19:30 sophiakp1safety.pl*
-rwxr-xr-x. 1 chem12x chem12x  16K Jul 15 19:30 sophiakp2mail.pl*
-rwxr-xr-x. 1 chem12x chem12x  15K Jul 15 19:30 sophiakp2.pl*

I need to explain. My granddaughter was studying chemical equilibrium in high school, so I wrote some programs to help her learn. By the time I'd finished, she had moved on. Oh well. Anyway, all these programs involve Computer Assisted Testing, which also includes teaching, learning, etc.. I converted sophiakp1.pl to include the lib statement we need (by hand) as proof of cocept. So now it is time to alter chatGPT's suggestion and try it.

  chem12x@chemphys cgi-bin]$ mkdir test

Next, we re-copy some Perl code from cgi-bin to cgi-bin/test as what we had was corrupted. Then chatGPT suggested:

#!/bin/sed -f

# Add a line of code above the first instance of "use"
/\<use\>/ {
    i\
    use lib '/home/chem12x/public_html/cgi-bin';
}
 Yes, hold on hold on
# Print all lines
1,$ p

This failed

  #!/bin/bash

# Save the awk script to a file named 'insert_code.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk -i inplace '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "# Line of code to insert"
        print
        found=1
        next
    }
    { print }
' {} \;

This didn't work either, so, iteration n+1 yields: "Apologies for the confusion. It seems there was a typo in the command. The -i inplace option is specific to sed, and awk does not have an equivalent option for in-place editing. Instead, we'll need to use a temporary file to achieve the desired effect. Here's the updated version using awk:"

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "# Line of code to insert"
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

chatCPK wrote the following:

"Replace /path/to/directory with the actual path to the 
directory containing your .pl files. Save the script 
above to a file named add_use.awk. 
Make sure to adjust # Line of code to insert with the 
actual code you want to insert.

This script will use awk to search for the first occurrence 
of "use" in each .pl file and then insert the desired line 
above it. The changes will be written to a temporary file, 
which is then moved back to the original file, effectively 
achieving the in-place editing.

Please give this script a try, and it should work as expected."

Most of this is wrong. I named the file add_use.sh and used "chmod a+x add_use.sh" to make it executable. Then, I copied everything in cgi-bin to a safety directory, chi-bin/safety.
Here is the final result:

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "use lib '/home/chem12x/public_html/cgi-bin';"
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

There's one last problem here, which had to be fixed.

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print qw(use lib '/home/chem12x/public_html/cgi-bin';)
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

Without the qw code, the single apostrophes are not reproduced into the final Perl programs. To see the result try this link.