$ sed ':again;$!N;$!b again; s/{[^}]*}//g' file
This is
that wants
anyway.
Explanation:
:again;$!N;$!b again;
This reads the whole file into the pattern space.
:again
is a label. N
reads in the next line. $!b again
branches back to the again
label on the condition that this is not the last line.
s/{[^}]*}//g
This removes all expressions in braces.
On Mac OSX, try:
sed -e ':again' -e N -e '$!b again' -e 's/{[^}]*}//g' file
Nested Braces
Let's take this as a test file with lots of nested braces:
a{b{c}d}e
1{2
}3{
}
5
Here is a modification to handle nested braces:
$ sed ':again;$!N;$!b again; :b; s/{[^{}]*}//g; t b' file2
ae
13
5
Explanation:
:again;$!N;$!b again
This is the same as before: it reads in the whole file.
:b
This defines a label b
.
s/{[^{}]*}//g
This removes text in braces as long as the text contains no inner braces.
t b
If the above substitute command resulted in a change, jump back to label b
. In this way, the substitute command is repeated until all brace-groups are removed.
I'd like to find a regular pattern to include in a shell script so
that n variables will contain the n arguments
The following creates a shell array arglist
that contains each of the arguments:
$ readarray -t arglist < <(echo "\command{arg1,
arg2 ,
arg3
}" | sed -n '/\\command/{ :a;/}/!{N;b a}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}')
By using the declare
statement, we can see that it worked:
$ declare -p arglist
declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3")'
Here is another example with the arguments on one line:
$ readarray -t arglist < <(echo "\command{arg1, arg2, arg3, arg4}" | sed -n '/\\command/{ :a;/}/!{N;b a}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}')
Again, it works:
$ declare -p arglist
declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3" [3]="arg4")'
Note that the space in < <(
is essential. We are redirecting input from a process substitution. Without the space, bash
will try something else entirely.
How it works
The sed
command is a bit subtle. Let's look at it a piece at a time:
-n
Don't print lines unless explicitly asked.
/\\command/{...}
If we find a line that contains \command
, then perform the commands found in the braces which are as follows:
:a;/}/!{N;b a}
This reads lines into the pattern buffer until we find a line that contains }
. This way, we get the whole command in at once.
s/\\command{//
Remove the \command{
string.
s/[ \n}]//g
Remove all spaces, closing braces, and newlines.
s/,/\n/g
Replace commas with newlines. When this is done, each argument is on a separate line which is what readarray
wants.
p
Print.
Best Answer
Replace
[some text]
by the empty string. Assuming you don't want to parse nested brackets, thesome text
can't contain any brackets.Note that in the bracket expression
[^][]
to match anything but[
or]
, the]
must come first. Normally a]
would end the character set, but if it's the first character in the set (here, after the^
complementation character), the]
stands for itself.If you do want to parse nested brackets, or if the bracketed text can span multiple lines, sed isn't the right tool.