Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the following string

y10_zcis y10_nom y10_infl y20_zcis y20_infl y30_zcis

I would like to transform this to

"y10_zcis", "y10_nom", "y10_infl", "y20_zcis", "y20_infl", "y30_zcis"

I accomplished something similar with the extremely ugly:

$ cat in.txt | sed 's/ /\'$'\n/g' | sed 's/\(.*\)/"\1",/g' | tr -d '\n'


"y10_zcis","y10_nom","y10_infl","y20_zcis","y20_infl","y30_zcis",

But that feels like an utter failure, and it doesn't take care of the last unwanted , (but perhaps this is best to just delete afterwards)

share|improve this question
up vote 5 down vote accepted

You can do

sed -e 's| |", "|g' -e 's|^|"|g' -e 's|$|"|g' in.txt

Where

  • 's| |", "|g' will replace every space with ", "
  • 's|^|"|g' while at the beginning there's no space, you must specify with ^ the beginning of the line, so you're telling, put " at the beginning.
  • 's|$|"|g' same thing but specifying the end of every line with $

UPDATE

As @don_crissti pointed out, you can do it shorter with the following

sed 's| |", "|g;s|.*|"&"|'

Where

  • ; separate each instruction
  • .* matches the entire line.
  • & an ampersand on the RHS is replaced by the entire expression matched on the LHS, in this case .*

    RHS=Right hand side

    LHS=Left hand side

share|improve this answer
    
Very nice, would you mind explaining how it works? Thanks – luffe Mar 4 at 18:37
    
@luffe updated! – tachomi Mar 4 at 18:41

Perhaps awk

awk -vOFS=', ' '{for (k=1; k<=NF; ++k) $k="\""$k"\""; print}' file
"y10_zcis", "y10_nom", "y10_infl", "y20_zcis", "y20_infl", "y30_zcis", "y30_nom", "y30_infl"
share|improve this answer

You can do:

sed 's/\([^ ]\+\)/"\1",/g; s/,$//' file.txt

Example:

% sed 's/\([^ ]\+\)/"\1",/g; s/,$//' <<<'y10_zcis y10_nom y10_infl y20_zcis y20_infl y30_zcis'   
"y10_zcis", "y10_nom", "y10_infl", "y20_zcis", "y20_infl", "y30_zcis"
share|improve this answer

Using Perl:

perl -lane '$,=", "; foreach(@F) {s/^|$/"/g; push(@f, $_)}; print(@f)' <<<'y10_zcis y10_nom y10_infl y20_zcis y20_infl y30_zcis'
  • $, = ", ": sets the output field separator to ,;
  • foreach(@F) {s/^|$/"/g; push(@f, $_)}: for each space-separated field, wraps the field into double quotes and appends it @f;
  • print(@f): prints the elements of @f separated by the output field separator.
% perl -lane '$,=", "; foreach(@F) {s/^|$/"/g; push(@f, $_)}; print(@f)' <<<'y10_zcis y10_nom y10_infl y20_zcis y20_infl y30_zcis'
"y10_zcis", "y10_nom", "y10_infl", "y20_zcis", "y20_infl", "y30_zcis"
%
share|improve this answer

Assuming you're using bash and your string is already in a variable:

$ a="y10_zcis y10_nom y10_infl y20_zcis y20_infl y30_zcis"
$ 

Then you can do this:

$ echo \"${a// /\", \"}\"
"y10_zcis", "y10_nom", "y10_infl", "y20_zcis", "y20_infl", "y30_zcis"
$ 
share|improve this answer

Yet Another Way, using the shell (for, printf), and a final sed hack:

( for word in $(cat in.txt)
    do printf '"%s", ' $word; done; 
  printf '"\n' ) | 
  sed 's/, "$//'
share|improve this answer
2  
Avoid the for stuff in $(cat file) construct... besides, you're already using sed so use only sed for this job. If you wanted to do it shell only, you could run (with bash4): mapfile -t stuff <infile; printf '"%s"\n' "${stuff[@]// /\", \"}" – don_crissti Mar 4 at 23:12

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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