I am looking for some hints, how I could achive a better, more elegant, efficient solution. So I've got a file containing a list of names.


Doe John
del Super Mario
van Hoppity Jenny
van der Hupfburg Susi
Smith-Osborne John Marc

Desired Output:

John Doe
Mario del Super
Jenny van Happity
Susi van der Hupfburg
John Marc Smith-Osborne

As you can see, the sort order is "family name" followed by "name" and no specific delimiter (just spaces) seperating family name from name. What I want is first name than family name. In most cases the first word is the family name. In some cases, there is a prefix like "van" or the italian "del". To attach these prefixex to the family name, I want to replace the spaces with a dash - so they become on word (van-Hoppity, van-der-Hupfburg, etc.) and i can move the first word to the end of line,

My current sed solution is working, but the line is getting longer and longer with every new prefix found.

So i want to use awk, with a file containing the search patterns (prefix list) that should find the pattern in the names file and replace it.

so 2 files

  • names.txt
  • pattern.txt

pattern.txt containing the prefixes and the substitute replacement in the second field. Field seperator is ";"


 del ;del-
 van der ;van-der-
 van ;van-

awk should use pattern.txt to search in names.txt and replace the found matches with the value of field 2 in pattern.txt

Any idea hints, suggestions?

  • But the substation pattern is much simpler, the family name prefixes appear to all be in lower case and the actual family name is capitalized, can’t you replace all occurrences of a space before the first [A-Z] with a hyphen ? Won’t that reduce all family names to a single word?
    – HBruijn
    Aug 24, 2022 at 9:21
  • Unfortunatly no. The actual file also contains capitalized prefixes in some cases like - Van Der / Del / DEL / DE / de etc. The given examples are just an excerpt and cover about 90% of the prefixes.
    – zippy-flop
    Aug 25, 2022 at 1:08

1 Answer 1


As far as I can see your text file (which is a horrible way to store such data) can be interpreted as:

  • each line contains a name
  • the family name, surname may start with a all-lower-case prefix of zero or more words (e.g. "van" , "del", "van der") followed by a capitalised word
    Implied: the list doesn't contain entries like "Von Doom Victor"
  • separated with a space from:
  • one or more first names

On possible regular expression to make a capture group of your (family Name) <space> (First Name(s)) is (^[^A-Z]*[A-Z][^ ]*) (.*$).

The regex I'm using is explained here: https://regex101.com/r/kOjwiS/1

and poured into a bash snippet :

regex="(^[^A-Z]*[A-Z][^ ]*) (.*$)" 
while read line ; do  
  [[ "$line" =~ $regex ]]
  echo "Firstname(s): ${BASH_REMATCH[2]}" 
  echo  "Family Name: ${BASH_REMATCH[1]}" 
done < names.txt

Firstname(s): John
Family Name: Doe
Firstname(s): Mario
Family Name: del Super
Firstname(s): Jenny
Family Name: van Hoppity
Firstname(s): Susi
Family Name: van der Hupfburg
Firstname(s): John Marc
Family Name: Smith-Osborne

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .