3

I'm parsing a document with a bash script and output different parts of it. At one point i need find and reformat text in the form of:

(foo)[X]
[Y]
(bar)[Z]

to something like:

X->foo
Y
Z->bar

Now, I'm able to grep the parts I want with RegEx, but I'm having trouble swapping the two elements in one line and handling the fact that the text in parentheses is optional. Is this even possible with a combination of sed and grep?

Thank You for your time.

3 Answers 3

3

You can use sed:

sed -e 's/(\([^)]*\))\[\([^]]*\)]/\2->\1/' -e 's/\[\([^]]*\)]/\1/' file

This works for your given input example:

X->foo
Y
Z->bar

You might need to make the patterns more strict if you have more kinds of input to handle.

Sign up to request clarification or add additional context in comments.

3 Comments

it really does. wow, seems like i still have a lot to learn about sed! could you maybe elaborate a little bit how you actually did the swapping with a simple substitute command? your code works and my problem is solved, but im having trouble completely understanding your code. thanks so much!
ok i think i got it, but shouldnt you escape the last " ] " in each of your substitutes?
That's great you figured it! No need to escape the closing ] when it is outside of a [...]. (If we needed to escape, my answer wouldn't work...)
2

You can use awk:

awk -F '[][()]+' '{print (NF>3 ? $3 "->" $2 : $2)}' file
X->foo
Y
Z->bar

2 Comments

your answer is the easiest to underand and yet i think ill stick with the sed solution. thank you for your time, i should really make myself familiar with awk.
sed cannot do it in one pass as you can see from 2 substitute commands in janos's answer.
1

You can even do it in bash itself, although it's not pretty.

# Three capture groups:
#  1. The optional paranthesized text
#  2. The contents of the parentheses
#  3. The contents of the square brackets
regex="(\((.*)\))?\[(.*)\]"

while IFS= read -r str; do
  [[ "$str" =~ $regex ]]

  # If the 2nd array element is not empty, print -> followed by the
  # non-empty value.
  echo "${BASH_REMATCH[3]}${BASH_REMATCH[2]:+->${BASH_REMATCH[2]}}"
done < file.txt

1 Comment

thanks for your effort, but i think i prefer the sed and awk methods :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.