Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a text file with each line having some defined number of fields but they can differ from line to line. All I want to do is to add "=" sign in front of every value in the field in that line.

For example INPUT FILE

A   B   C   D   E
P   Q   R   S   T   U
L   M   N   O

OUTPUT FILE

=A  =B  =C  =D  =E
=P  =Q  =R  =S  =T  =U
=L  =M  =N  =O

Also this is just an example, my file contains some lines where number of field are more than 20. How to do this efficiently.

share|improve this question

6 Answers 6

up vote 3 down vote accepted

To do this in awk, you could use:

awk '{for (i=1;i<=NF;i++) printf "=%s ",$i;printf "\n"}' filename

Loop over the internal NF (number of fields) variable, printing each field with an equals prepended and a space appended, then after printing all fields, print a newline.

share|improve this answer
    
Hi this works. Thanks a lot. Can you tell why printf is used and not print??? –  user3138373 May 14 at 15:39
2  
print adds a newline by default, printf does not –  Josh Jolly May 14 at 17:19
    
Note that it changes the spacing of the fields. –  Stéphane Chazelas May 15 at 6:13

Your question is not very clear.

To insert = before each sequence of letters, that would be:

sed 's/[[:alpha:]]\{1,\}/=&/g'

Before any letter:

sed 's/[[:alpha:]]/=&/g'

Before each sequence of non-blanks:

sed 's/[^[:blank:]]\{1,\}/=&/g'

(those are POSIX and portable).

share|improve this answer

Assuming your fields contain more than just one letter, with GNU sed:

sed 's/\</=/g' <<END
foo    bar    baz
A      B      C
apple  banana cherry
END
=foo    =bar    =baz
=A      =B      =C
=apple  =banana =cherry

GNU sed's \< regex construct is a zero-width "start of word" marker (the transition between a non-word (or the beginning of the line) and a word character (alnums in your locale or underscore)). So we're replacing the start of each word with the "=" character.

(sed regex reference here)

share|improve this answer
    
Tangentially, I wonder why Perl's regex syntax does not have "start of word" and "end of word" markers. –  glenn jackman May 14 at 17:02
    
Maybe \b\w for work around. –  Gnouc May 14 at 17:29
    
good idea. \b(?=\w) would be more exact. Thanks. –  glenn jackman May 14 at 18:08
    
Ah, I forgot to update my comment, I used \b(?=\w) in my answer :) –  Gnouc May 14 at 18:20
    
Though \< originated in BSDs (ex/grep), it seems it never made it to any BSD sed. It is in GNU sed though. It's not POSIX. –  Stéphane Chazelas May 14 at 18:23

A shorter awk version:

$ awk 'gsub(/([^ ]+)/,"=&",$0)' file
=A   =B   =C   =D   =E
=P   =Q   =R   =S   =T   =U
=L   =M   =N   =O

Explanation

We do a global substitution for each input line:

  • /([^ ]+)/: matchs each fields, because fields is separate by spaces, so this regex match all thing except spaces.

  • "=&": with each fields, add = before it.

& meaning is replaced with character that was matched. From man awk:

gsub(r, s [, t])        For each substring matching the regular expres‐
                        sion  r  in the string t, substitute the string
                        s, and return the number of substitutions.   If
                        t  is  not  supplied,  use  $0.   An  &  in the
                        replacement text is replaced with the text that
                        was  actually matched.  Use \& to get a literal
                        &.  (This must be typed  as  "\\&";  see  GAWK:
                        Effective  AWK Programming for a fuller discus‐
                        sion of the rules for &'s  and  backslashes  in
                        the replacement text of sub(), gsub(), and gen‐
                        sub().)

Update

For @glenn jackman's answer and comment, I add an equivalent version in perl:

$ perl -pe 's/\b(?=\w)/=$&/g' file
=A   =B   =C   =D   =E
=P   =Q   =R   =S   =T   =U
=L   =M   =N   =O
share|improve this answer
    
Note that the awk one removes the blank lines. –  Stéphane Chazelas May 15 at 6:15
    
@StephaneChazelas: awk 'NF > 0 {gsub(/([^ ]+)/,"=&",$0)}{print}' will keep blank lines. –  Gnouc May 15 at 6:19
    
Or just awk '{gsub(/([^ ]+)/,"=&");print}', or awk '1+gsub(/([^ ]+)/,"=&")',it's just that you were using the result of gsub as a condition to print. –  Stéphane Chazelas May 15 at 7:22
    
@StephaneChazelas: Maybe I think a complicated way. Thanks for good point. –  Gnouc May 15 at 7:43

You can simplify this a bit with GNU awk

awk -v RS='[[:space:]]+' '{printf "=%s%s", $0,RT}' input.file
=A   =B   =C   =D   =E
=P   =Q   =R   =S   =T   =U
=L   =M   =N   =O
share|improve this answer
    
This Works , Can you explain the code? THanks –  user3138373 May 14 at 16:01

Try this simple sed command,

sed 's/\([A-Za-z]\+\)/=\1/g' file

Example:

$ (echo 'A   B   C'; echo 'A C D F') | sed 's/\([A-Za-z]\+\)/=\1/g'
=A   =B   =C
=A =C =D =F

This command will place = sign before A-Z,a-z.

OR

try this command also,

sed 's/\([ ]\+\)/\1=/g; s/^\(.*\)$/=\1/g' file

Example:

$ (echo 'A   B   C'; echo 'A C D F') | sed 's/\([ ]\+\)/\1=/g; s/^\(.*\)$/=\1/g'
=A   =B   =C
=A =C =D =F

This command will replace one or more spaces with one or more spaces plus = sign and also it places = on starting.

share|improve this answer

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.