Jirr Sawaf
Jirr Sawaf

Reputation: 143

How to add a space before and after certain characters using sed or awk?

I know that I can add space after or before a character using

sed -i 's/char/char /g' fname.txt

However, I need help adding space before and after these characters ```[]<>'''

for example,

nie[breath]hi
hi </langenglish>'tjie

would turn into

nie [breath] hi
hi </langenglish> 'tjie

NOTE: that i want a single space after <>[] because using the first code, I would essentially get two spaces.

Please let me know how I could accomplish this task.

Upvotes: 1

Views: 2608

Answers (3)

Ed Morton
Ed Morton

Reputation: 203712

From your example it seems like you're mis-specifying your problem and you actually want a space before and after every [...] or <...> string rather than before and after every [, ], <, or > character. If that's correct then using any sed that allows \n to represent a newline in the regexp and replacement text (e.g. GNU sed):

$ sed 's/ /\n/g; s/\[[^]]*]/ & /g; s/<[^>]*>/ & /g; s/ *\n */ /g' file
nie [breath] hi
hi </langenglish> 'tjie

or with any awk:

$ awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1' file
nie [breath] hi
hi </langenglish> 'tjie

You should add some non-sunny-day test cases to your example to make sure you get what you really need, e.g.:

$ echo 'head[foo<bar]tail' | awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1'
head [foo<bar] tail

$ echo 'head<foo<bar>tail' | awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1'
head <foo<bar> tail

$ echo 'head<foo[bar>tail' | awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1'
head <foo[bar> tail

$ echo 'head<foo]bar>tail' | awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1'
head <foo]bar> tail

$ echo 'head<foo[bar]tail' | awk '{gsub(/ /,"\n"); gsub(/\[[^]]*]/," & "); gsub(/<[^>]*>/," & "); gsub(/ *\n */," ")} 1'
head<foo [bar] tail

Upvotes: 4

RavinderSingh13
RavinderSingh13

Reputation: 133545

Could you please try following. Written as per shown samples only. This will add spaces before [ and < then it will add spaces after > and ]. As per shown samples.

awk '{gsub(/\[|</," &");gsub(/\]|>/,"& ")} 1' Input_file

Explanation: simply globally substituting [ and > with spaces before their values in first gsub. Then performing second global substitution to add spaces after > and ].

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626950

You can use sed like

sed 's/[[:space:]]*\([]>]\)[[:space:]]*/\1 /g;s/[[:space:]]*\([[<]\)[[:space:]]*/ \1/g' file > newfile

See an online demo:

s="nie[breath]hi
hi </langenglish>'tjie"
sed 's/[[:space:]]*\([]>]\)[[:space:]]*/\1 /g;s/[[:space:]]*\([[<]\)[[:space:]]*/ \1/g' <<< "$s"

Output:

nie [breath] hi
hi </langenglish> 'tjie

Details:

  • s/[[:space:]]*\([]>]\)[[:space:]]*/\1 /g - "normalizes" whitespace before ] and > chars by removing all whitespace before and keeping one after
  • s/[[:space:]]*\([[<]\)[[:space:]]*/ \1/g - "normalizes" whitespace before [ and < chars by removing all whitespace after and keeping one before

Upvotes: 0

Related Questions