1

How can I efficiently remove enclosing brackets from a file with bash scripting (first occurrence of [ and last occurrence of ] in file)? All brackets that are nested within the outer brackets and may extend over several lines should be retained. Leading or trailing whitespaces may be present.

content of file1

[
  Lorem ipsum
  [dolor] sit [amet
  conse] sadip elitr
]

cat file1 | magicCommand

desired output

  Lorem ipsum
  [dolor] sit [amet
  conse] sadip elitr

content of file2

  [Lorem ipsum [dolor] sit [amet conse] sadip elitr]

cat file2 | magicCommand

desired output

  Lorem ipsum [dolor] sit [amet conse] sadip elitr
oguz ismail
  • 1
  • 16
  • 47
  • 69
jpseng
  • 1,618
  • 6
  • 18

3 Answers3

3

If you want to edit the file to remove the braces, use ed:

printf '%s\n' '1s/^\([[:space:]]*\)\[/\1/' '$s/\]\([[:space:]]*\)$/\1/' w | ed -s file1

If you want to pass on the modified contents of the file to something else as part of a pipeline, use sed:

sed -e '1s/^\([[:space:]]*\)\[/\1/' -e '$s/\]\([[:space:]]*\)$/\1/' file1

Both of these will, for the first line of the file, remove a [ at the start of the line (Skipping over any initial whitespace before the opening brace), and for the last line of the file (Which can be the same line as in your second example), remove a ] at the end of the line (Not counting any trailing whitespace after the close bracket). Any leading/trailing whitespace will be preserved in the result; use s/...// instead to remove them too.

Shawn
  • 47,241
  • 3
  • 26
  • 60
1
perl -0777 -pe 's/^\s*\[\s*//; s/\s*\]\s*$//' file

That's aggressive about removing all whitespace around the outer brackets, which isn't exactly what you show in your desired output.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • as I do not need the leading or trailing whitespaces your solution is also exciting, especially as it is even shorter than using `sed` ... thanks – jpseng Jun 30 '21 at 11:16
  • This will be more memory intensive than the sed call: this perl will read the entire file into memory, the sed reads a line at a time. If your files are not large, then this will be faster. – glenn jackman Jun 30 '21 at 12:41
1

With GNU sed for -E and -z:

$ sed -Ez 's/\[(.*)]/\1/' file1

  Lorem ipsum
  [dolor] sit [amet
  conse] sadip elitr

$ sed -Ez 's/\[(.*)]/\1/' file2
  Lorem ipsum [dolor] sit [amet conse] sadip elitr

The above will read the whole file into memory.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185