4

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)

6 Answers 6

6

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

2
  • Very nice, would you mind explaining how it works? Thanks Commented Mar 4, 2016 at 18:37
  • @luffe updated! Commented Mar 4, 2016 at 18:41
5

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" 
3

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" 
2

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" % 
2

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" $ 
1

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/, "$//' 
1
  • 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[@]// /\", \"}" Commented Mar 4, 2016 at 23:12

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.