'+' (one or more occurrences) not working with 'sed' command
Frecuentes
Visto 40,517 veces
89
I'm trying to refine my code by getting rid of unnecessary white spaces, empty lines, and having parentheses balanced with a space in between them, so:
int a = 4;
if ((a==4) || (b==5))
a++ ;
debería cambiar a:
int a = 4;
if ( (a==4) || (b==5) )
a++ ;
It does work for the brackets and empty lines. However, it forgets to reduce the multiple spaces to one space:
int a = 4;
if ( (a==4) || (b==5) )
a++ ;
Aquí está mi guión:
#!/bin/bash
# Script to refine code
#
filename=read.txt
sed 's/((/( (/g' $filename > new.txt
mv new.txt $filename
sed 's/))/) )/g' $filename > new.txt
mv new.txt $filename
sed 's/ +/ /g' $filename > new.txt
mv new.txt $filename
sed '/^$/d' $filename > new.txt
mv new.txt $filename
Also, is there a way to make this script more concise, e.g. removing or reducing the number of commands?
6 Respuestas
97
Si está utilizando base de datos GNU entonces necesitas usar sed -r
que fuerzas sed
to use extended regular expressions, including the wanted behavior of +
. Vea man sed
:
-r, --regexp-extended
use extended regular expressions in the script.
The same holds if you are using OS X sed, but then you need to use sed -E
:
-E Interpret regular expressions as extended (modern) regular expressions
rather than basic regular regular expressions (BRE's).
respondido 30 mar '16, 07:03
-r seemed to be an illegal option but I did a man sed for use of extended regular expressions and it showed up '-E'. Tried it and Bingo! it worked! Thanks! But I'm confused now, the use of '*' worked but for the use of '+' I had to use the -E flag? - Siddhartha
Am I correct in that you are using OS X? -r
trabaja para GNU sed
, pero OS X sed
indeed needs -E
to use the extended (modern) regular expressions. Both make a distinction between enlace y modernas regular expressions and +
is interpreted as a ordinary character in the enlace funcionamiento de sed
. Vea esta referencia: Obsolete (''basic'') regular expressions differ in several respects (...) '+' and '?' are ordinary characters (...). - Sico
Yeh use -E for OSX instead of -r - Robar
If you use homebrew on OS X, you can install the GNU version of sed (gnu-sed
) y usa el gsed
command to emulate the normal behavior. (I do this to avoid having to learn the different behaviors of UNIX/BSD sed) - andiras
@ThorSummoner: not just *nix, include the .Net engine, JavaScript, Perl (which is now different to PCRE), Python, Java, etc... See choonsiong.com/public/books/… - oscuro
20
You have to preceed +
con un \
, De lo contrario sed
tries to match the character +
misma.
To make the script "smarter", you can accumulate all the expressions in one sed:
sed -e 's/((/( (/g' -e 's/))/) )/g' -e 's/ \+/ /g' -e '/^$/d' $filename > new.txt
Algunas implementaciones de sed
even support the -i
option that enables changing the file en su lugar.
Respondido 24 ago 12, 03:08
preceding with \ didn't work.. -i flag gives the error: sed: -i may not be used with stdin - Siddhartha
the accumulation doesn't work :( I couldn't find how to next sed commands online, is using 'awk' a better option? if so how? Appreciate any help. - Siddhartha
@ Siddhartha: -i
only works with files, not with stdin. How could you change stdin in place? You could also try semicolons for accumulation: sed -e 's///;s///;...'
- enfermedad
Ok so I got the accumulation to work, but I can't get the -E flag to fit in anywhere!: - Siddhartha
I don't think MacOS sed
admite múltiples -e
options. Use semicolons or newlines between the individual script commands, and put them all in a single quoted string. Also on MacOS the -i
option needs an argument; you can pass it an empty string if you don't want a backup. So sed -i '' -E 's///;s///;...' "$filename"
- triples
13
Sometimes, -r and -e won't work. I'm using sed version 4.2.1 and they aren't working for me at all.
A quick hack is to use the * operator instead. So let's say we want to replace all redundant space characters with a single space: We'd like to do:
sed 's/ +/ /'
But we can use this instead:
sed 's/ */ /'
(note the double-space)
Respondido 17 Oct 18, 16:10
This is what I've always used in its place. It works with everything. It's not really a hack, just a modification of "zero or more" - "one plus zero or more" = "one or more" - jon v
4
May not be the cleanest solution. But if you want to avoid -E
y -r
to remain compatible with both versions of sed, you can do a repeat character cc*
- that's 1 c
then 0 or more c
's ==
1 o más c
es
Or just use the BRE syntax, as suggested by @cdarke, to match a specific number or patternsc\{1,\}
. The second number after the comma is excluded to mean 1 or more.
Respondido 28 Feb 18, 20:02
1
Esto podría funcionar para ti:
sed -e '/^$/d' -e ':a' -e 's/\([()]\)\1/\1 \1/g' -e 'ta' -e 's/ */ /g' $filename >new.txt
Respondido 24 ago 12, 06:08
0
on the bash front;
First I made a script test.sh
cat test.sh
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
SRC=`echo $line | awk '{print $1}'`
DEST=`echo $line | awk '{print $2}'`
echo "moving $SRC to $DEST"
mv $SRC $DEST || echo "move $SRC to $DEST failed" && exit 1
done < "$1"
then we make a data file and a test file aaa.txt
cat aaa.txt
<tag1>19</tag1>
<tag2>2</tag2>
<tag3>-12</tag3>
<tag4>37</tag4>
<tag5>-41</tag5>
then test and show results.
bash test.sh list.txt
Text read from file: aaa.txt bbb.txt
moving aaa.txt to bbb.txt
Respondido el 15 de enero de 16 a las 16:01
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas macos bash sed or haz tu propia pregunta.
By the way, in BRE you can use
\{1,\}
en lugar de+
- cdarke@cdarke, I don't understand, does that also give u multiple spaces? - Siddhartha
/ \{1,\}/
means "one or more spaces", yes. - cdarke@cdarke your answer is great. I edited the accepted answer to include your helpful comment! - Overbryd