Ben
Ben

Reputation: 2269

Use grep xargs sed to regenerate UUIDs in a file more effeciently

I successfully am able to replace UUIDs with freshly generated UUIDDs in a file:

FILE=/home/username/sql_inserts_with_uuid.sql
grep -i -o -E "([a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12})" $FILE | xargs -I {} sed -i "s/{}/`uuidgen -t`/g" $FILE

But its slow because it rewrites the file for each UUID it generates. Is there a more efficient way to rewrite every UUID in a single pass instead of rewriting the same file over and over?

Save this sample data in a file to test:

INSERT INTO fake_table (uuid) VALUES ('812ab76e-43ca-11ec-b54f-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('854f7b36-43ca-11ec-9608-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8a09444a-43ca-11ec-8ae2-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8cd0da58-43ca-11ec-9811-00d8617c2296');
INSERT INTO fake_table (uuid) VALUES ('8f9889c0-43ca-11ec-8bfc-00d8617c2296');

Upvotes: 2

Views: 329

Answers (2)

M. Nejat Aydin
M. Nejat Aydin

Reputation: 10123

In plain bash:

cat new_uuids

#!/bin/bash

hex='[[:xdigit:]]'
hex3="$hex$hex$hex"
hex4="$hex3$hex"
hex8="$hex4$hex4"
hex12="$hex8$hex4"
pat="$hex8-$hex4-[0-9]$hex3-[89aAbB]$hex3-$hex12"

while IFS= read -r line; do
    if [[ $line = *$pat* ]]; then
        echo "${line/$pat/$(uuidgen -t)}"
    else
        echo "$line"
    fi
done

Call it as

./new_uuids < sql_inserts_with_uuid.sql > new_sql_inserts_with_uuid.sql

Upvotes: 1

dawg
dawg

Reputation: 103774

You can use awk with a system call to replace them all in one pass:

awk '
BEGIN{pat="[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[0-9][a-fA-F0-9]{3}-[89aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}"}
function get_uuid(){
    cmd = "uuidgen"
    cmd | getline uuid
    close(cmd)
    return uuid
}

$0~pat{     
    uuid=get_uuid()
    sub(pat,uuid,$0)
} 1
' file.txt

Prints:

INSERT INTO fake_table (uuid) VALUES ('473C4331-CC31-4FD0-AE99-37FA7E5F23CF');
INSERT INTO fake_table (uuid) VALUES ('EBEC05AB-4236-4384-AF7A-76D4A0615599');
INSERT INTO fake_table (uuid) VALUES ('23740143-6CC1-41FC-8AE7-038810291026');
INSERT INTO fake_table (uuid) VALUES ('7DBF25AF-4E85-4C55-B8CA-0F6150D5DD3C');
INSERT INTO fake_table (uuid) VALUES ('4365127B-EB46-414E-92D4-B48CC211489E');

With GNU awk, you can make the replacements inplace. Otherwise, you need to redirect the output of this to a temp file then mv the temp file on top of the source file. This sounds harder than is actually is.


Speed test: Multiplying your example file to 10,000 UUID replacements, the file is processed in 21 seconds on my computer and 26 ms if the same file has no replacements. The system call is not free in terms of efficiency but this is likely faster than what you are doing...

Upvotes: 2

Related Questions