Use sed to replace letters [a-z] and [A-Z] and ['] with underscores

Viewed 846

...for all characters but the first letter of every word on a line excluding the first word. All text is English language.

Would like to use sed to convert input like this:

Mary had a little lamb
It's fleece was white as snow

to this:

Mary h__ a l_____ l___
It's f_____ w__ w____ a_ s___

For a project that looks at cued recall.

Looked at several intros to sed and regex. Would be using the flavor of sed on the terminal shipped with MacOS 10.14.5.

3 Answers

This might work for you (GNU sed):

sed -E 'h;y/'\''/x/;s/\B./_/g;G;s/\S+\s*(.*)\n(\S+\s*).*/\2\1/' file

Make a copy of the current line in the hold space. Translate ''s to `x's so that such words can be filled with underscores other than the first letter of each word. Append the copied line and using grouping and back references replace the first word of the line unadulterated.

sed is for doing simple s/old/new operations on individual strings, that is all. For anything else you should be using awk, e.g. with GNU awk for the 3rd arg to match():

$ awk '{
    out = $1
    $1 = ""
    while ( match($0,/(\S)(\S*)(.*)/,a) ) {
        out = out OFS a[1] gensub(/./,"_","g",a[2])
        $0 = a[3]
    }
    print out $0
}' file
Mary h__ a l_____ l___
It's f_____ w__ w____ a_ s___

With any awk in any shell on every UNIX box including the default awk on MacOS:

$ awk '{
    out = $1
    $1 = ""
    while ( match($0,/[^[:space:]][^[:space:]]*/) ) {
        str = substr($0,RSTART+1,RLENGTH-1)
        gsub(/./,"_",str)
        out = out OFS substr($0,RSTART,1) str
        $0 = substr($0,RSTART+RLENGTH)
    }
    print out $0
}' file
Mary h__ a l_____ l___
It's f_____ w__ w____ a_ s___

Here is another awk script (all awk versions), I enjoyed creating for this quest.

script.awk

{
    for (i = 2; i <= NF; i++) {    # for each input word starting from 2nd word
        head = substr($i,1,1);     # output word head is first letter from current field
        tail = substr("____________________________", 1, length($i) - 1); # output word tail is computed from template word
        $i = head tail;            # recreate current input word from head and tail
    }
    print;                         # output the converted line
}

input.txt

Mary had a little lamb
It's fleece was white as snow

run:

awk -f script.awk input.txt

this could be also condensed into single line:

awk '{for (i = 2; i <= NF; i++) $i = substr($i,1,1) substr("____________________________", 1, length($i) - 1); print }' input.txt

output is:

Mary h__ a l_____ l____
It's f_____ w__ w____ a_ s___

I enjoyed this task.

Related