“ +”(一个或多个事件)不与“ sed”命令一起使用


73

我正在尝试通过消除不必要的空格,空行以及使括号与空格之间保持平衡来完善代码,因此:

    int a = 4;
    if ((a==4) ||   (b==5))

    a++   ;

应更改为:

    int a = 4;
    if ( (a==4) || (b==5) )
    a++ ;

它确实适用于方括号和空行。但是,它忘记将多个空间缩小为一个空间:

    int a = 4;
    if ( (a==4) ||   (b==5) )
    a++    ;

这是我的脚本:

    #!/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

另外,有没有办法使此脚本更简洁,例如删除或减少命令数量?


5
顺便说一句,在BRE中,您可以使用\{1,\}而不是+
cdarke 2012年

@cdarke,我不明白,这还会给您多个空格吗?
悉达多

/ \{1,\}/表示“一个或多个空格”,是的。
cdarke

@cdarke,您的回答很棒。我编辑了接受的答案,以包括您的有用评论!
2016年

Answers:


82

如果您使用的是GNU sed,则需要使用sed -r哪些强制sed来使用扩展的正则表达式,包括的所需行为+。见man sed

-r, --regexp-extended

       use extended regular expressions in the script.

如果您使用的是OS X sed,则保持不变,但是您需要使用sed -E

-E      Interpret regular expressions as extended (modern) regular expressions
        rather than basic regular regular expressions (BRE's).

4
-r似乎是非法的选择,但我对扩展的正则表达式使用了一个sed命令,它显示为'-E'。尝试过和宾果游戏!有效!谢谢!但是我现在很困惑,使用'*'有效,但是对于使用'+'我必须使用-E标志?
Siddhartha 2012年

9
我使用您的OS X是正确的吗?-r适用于GNU sed,但OS X sed确实需要-E使用扩展的(现代)正则表达式。两者都区分了基本现代正则表达式,+并解释为的基本功能中的普通字符sed。参见该参考过时(“基本”)正则表达式在几个方面有所不同(...)“ +”和“?” 是普通字符(...)
西科

1
是的,在OSX中使用-E而不是-r
Rob

如果在OS X上使用自制软件,则可以安装sed(gnu-sed)的GNU版本,并使用该gsed命令模拟正常行为。(我这样做是为了避免学习UNIX / BSD sed的不同行为)
andyras

1
@ThorSummoner:不仅是* nix,还包括.Net引擎,JavaScript,Perl(现在与PCRE有所不同),Python,Java等...请参见choonsiong.com/public/books/…–
cdarke

16

你必须preceed+\,否则sed会尝试将匹配字符+本身。

为了使脚本“更智能”,您可以将所有表达式累积在一个sed中:

sed -e 's/((/( (/g' -e 's/))/) )/g' -e 's/ \+/ /g' -e '/^$/d' $filename > new.txt

的某些实现sed甚至支持-i启用就地更改文件的选项。


1
-i标志给出错误:sed:-i可能不适用于stdin
Siddhartha 2012年

积累不工作:(我怎么也找不到下一个sed命令在网上,使用“AWK”一个更好的选择,如果又如何得到任何帮助??
悉达多

@Siddhartha:-i仅适用于文件,不适用于stdin。您如何更改标准输入?您还可以尝试使用分号进行累加:sed -e 's///;s///;...'
choroba 2012年

好的,这样我就可以积累工作了,但是我无法使-E标志适合任何地方!:
Siddhartha 2012年

2
我不认为MacOSsed支持多种-e选择。在各个脚本命令之间使用分号或换行符,并将它们全部放在单个引号中。同样在MacOS上,该-i选项还需要一个参数。如果您不想备份,则可以向其传递一个空字符串。所以sed -i '' -E 's///;s///;...' "$filename"
Tripleee

10

有时-r和-e无效。我使用的是sed 4.2.1版,它们根本不适合我。

一个快速的技巧是改用*运算符。假设我们要用一个空格替换所有多余的空格字符:我们想这样做:

sed 's/ +/ /'

但是我们可以改用这个:

sed 's/  */ /'

(请注意双空格)


3
这就是我一直使用的位置。它适用于一切。这不是真正的黑客,只是对“零个或多个”的修改-“一个加零个或多个” =“一个或多个”
Jon V

3

可能不是最干净的解决方案。但是,如果要避免-E-r保持与sed的两个版本兼容,则可以执行重复字符cc*-等于1,c然后等于0或更大c,等于==1或更大c

或者只是使用@cdarke建议的BRE语法来匹配特定的数字或模式c\{1,\}。逗号后的第二个数字被排除是指1或更大。


1

这可能对您有用:

sed -e '/^$/d' -e ':a' -e 's/\([()]\)\1/\1 \1/g' -e 'ta' -e 's/  */ /g' $filename >new.txt

1

在猛烈的打击

首先我做了一个脚本test.sh

猫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"

然后我们制作一个数据文件和一个测试文件aaa.txt

cat aaa.txt
<tag1>19</tag1>
<tag2>2</tag2>
<tag3>-12</tag3>
<tag4>37</tag4>
<tag5>-41</tag5>

然后测试并显示结果。

bash test.sh list.txt 
Text read from file: aaa.txt bbb.txt
moving aaa.txt to bbb.txt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.