regexlinuxbashsed

How to use Linux sed command to create this output?


I have a file with the name fks containing the following content:

ALTER TABLE "USER01"."TB01" ADD CONSTRAINT "TB01FK" FOREIGN KEY ("IDUSUARIO") REFERENCES "USER02"."TB02";

I need a script to produce this output based in my fks file content:

grant references on "USER02"."TB02" to "USER01";

Here is my current Bash script:

#!/bin/bash
# Read the 'fks' file line by line
cat fks | while read line; do
  # Extract the source schema (after "ALTER TABLE " and before the ".")
  schema_origin=$(echo $line | sed -E 's/ALTER TABLE "([^"]+)".*/\1/' | tr '[:upper:]' '[:lower:]')
  
  # Extract the referenced schema (after "REFERENCES " and before ".")
  schema_referenced=$(echo $line | sed -E 's/.*REFERENCES "([^"]+)".*/\1/')
  
  # Extract the referenced table name (after the last ".")
  table_referenced=$(echo $line | sed -E 's/.*\.([^"]+)".*/\1/')
  
  # Generate the GRANT statement with the referenced schema and table
  echo "grant references on \"$schema_referenced\".\"$table_referenced\" to \"$schema_origin\";"
done

However, the output is incorrect:

grant references on "USER02" to "USER01";

I need help correcting the script so that it correctly outputs the full referenced schema and table.


Solution

  • .*\.([^"]+)".* matches a period not followed by a double quote, while you want to match ."TABLE"...

    Anyway, you don't need bash loops and several sed for this. One single sed run is enough to process each line of the file and to extract the different components:

    sed -E 's/.*ALTER[[:space:]]+TABLE[[:space:]]+("[^"]*").*[[:space:]]+REFERENCES[[:space:]]+("[^"]*"[.]"[^"]*").*/grant references on \2 to \1;/i' fks
    

    With GNU sed:

    sed -E 's/.*ALTER\s+TABLE\s+("[^"]*").*\s+REFERENCES\s+("[^"]*"[.]"[^"]*").*/grant references on \2 to \1;/i' fks
    

    If the ALTER TABLE part is always at the beginning of the line and the reference is always the last token we can simplify a bit:

    sed -E 's/^[^"]*("[^"]*").*("[^"]*"[.]"[^"]*");$/grant references on \2 to \1;/i' fks
    

    If you want a lower case output and your sed is GNU sed:

    sed -E 's/^[^"]*("[^"]*").*("[^"]*"[.]"[^"]*");$/\Lgrant references on \2 to \1;/i' fks