some name;another thing; random; value value value value value

I'm trying to replace the spaces that occur after the random; using sed. It's important to keep the spaces that is in some name for example.

This replaces all spaces with comma. How could I match a expression like *;*;*; and use sed with the rest of the line and replace spaces with comma?

sed -e 's/ /,/g'


  • 2
    To clarify, you only want to replace spaces that occur after the final semicolon, correct? Oct 10 '19 at 17:41

Using gsub() in awk on the last ;-delimited field:

$ awk -F ';' 'BEGIN { OFS=FS } { gsub(" ", ",", $NF); print }' file
some name;another thing; random;,value,value,value,value,value

Using sed and assuming we'd like to replace all spaces after the last ; with commas:

$ sed 'h;s/.*;//;y/ /,/;x;s/;[^;]*$//;G;s/\n/;/' file
some name;another thing; random;,value,value,value,value,value

Annotated sed script:

h               ; # Duplicate line into hold space
s/.*;//         ; # Delete up to the last ;
y/ /,/          ; # Change space to comma in remaining data
x               ; # Swap pattern and hold spaces
s/;[^;]*$//     ; # Delete from the last ;
G               ; # Append hold space delimited by newline
s/\n/;/         ; # Replace the embedded newline with ;
                ; # (implicit print)

The "hold space" is a separate storage buffer that sed provides. The "pattern space" is the buffer into which the data is read from the input and to which modifications may be applied.

  • Your awk worked perfectly. The sed looks awful :)
    – JoakimE
    Oct 10 '19 at 9:48
  • @Starlord sed is a neat little language, but can be difficult to decipher, yes. That sed code could also probably be made shorter, but it'll do the job.
    – Kusalananda
    Oct 10 '19 at 9:50

Perl to the rescue!

perl -F';' -ne '$F[3] =~ s/ /,/g; print join ";", @F'
  • -n reads the input line by line and process each line
  • -F splits each line on the given regular expression into the @F array
  • =~ binds the substitution only to the fourth element of the @F array, i.e. after the element after "random"
  • join joins back the elements of the @F array into the output string

With GNU sed

$ s='some name;another thing; random; value value value value value'
$ echo "$s" | sed -E ':a s/^(.*random;.*) /\1,/; ta'
some name;another thing; random;,value,value,value,value,value
  • :a label a
  • s/^(.*random;.*) /\1,/ here (.*random;.*) will capture everything till random; in the input line and as many characters as needed till there is a space afterwards, then in the replacement section use backreference to preserve the captured string and change space to comma character
    • note that if there are more than one random; in the input, this will preserve spaces only till the first occurrence
  • ta branch to label a if the previous substitution succeeded
$ perl -pe 's/ (?=[^;]*$)/,/g' file
  • Only those spaces that don't see a semicolon all the way to the end of line are selected for substitution.
$ perl -MText::CSV_XS=csv -e'csv(in=>csv(in=>"file",sep=>";",allow_whitespace=>1),sep=>";",quote_space=>0);'
some name;another thing;random;value value value value value

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.