如果声明正则表达式或坏回声? (bash 3.0)

时间:2011-12-07 00:24:30

标签: bash if-statement solaris echo

谁能告诉我为什么会这样?我试图在发生给定字符串之前插入一些行,比如说......

thing
extern void hello_dude(char *loc, long length){
thing

thing
another
extern void hello_dude(char *loc, long length){
thing

使用一个简单的(叹气)bash 3.0脚本,问题是我使用匹配字符串的if语句是回显像这样拆分的行:

thing
another
extern
void
hello_dude(char
*loc,
long
length){
thing

声明是

elif [[ "$LINE" =~ *hello_dude\(* ]]; then
    echo "$LINE" >> temp2
显然,在elif之前工作正常的领先if语句。

我尝试过每一个引用的味道和正则表达式,我可以想象......

任何帮助将不胜感激

编辑:这是使用

的实际脚本
#!/bin/bash

for LINE in `(cat temp1)`
do
  if [[ "$LINE" = sendMessage4K* ]]; then
     echo '/*---RUAISI---*/' >> temp2
     echo "$LINE" >> temp2
   elif [[ "$LINE" =~ *alpha_display\(* ]]; then
     echo "$LINE" >> temp2
     echo '/*---RUAISI---*/' >> temp2
  else
     echo "$LINE" >> temp2
  fi
done

temp1文件是:

FIX
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern void alpha_display(char *loc, long length){
  FIX
}
FIX

想法是通过以下方式获得temp2:

FIX
/*---RUAISI---*/
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern void alpha_display(char *loc, long length){
/*---RUAISI---*/
  FIX
}
FIX

但是我得到了这个

FIX
/*---RUAISI---*/
sendMessage4K(NomRPC,sbuffer,"KP07");
FIX
extern
void
alpha_display(char
/*---RUAISI---*/
*loc,
long
length){
FIX
}
FIX

3 个答案:

答案 0 :(得分:1)

如果没有看到您的脚本,我们就无法帮助您。但是,这种问题 - 在特定匹配模式之前插入一行文本 - 通常使用sed来处理。例如,如果我有一个如下所示的文件:

one
two
three

我想插入" Bananas"在"两个"之前,我会做这样的事情:

sed' / two / i \ Bananas'

这给了我:

one
Bananas
two
three

这假设GNU sed(虽然它也适用于其他版本的sed的微小修改)。

答案 1 :(得分:1)

您正在使用正则表达式匹配operator =〜,但在其右侧,没有正则表达式,而是shell通配符表达式。所以,将其改为

[[ $LINE == *hello_dude\(* ]]

[[ $LINE =~ hello_dude\( ]]

即。使用适当的运算符使用通配符,或使用正确的运算符使用正则表达式。

更新:查看更新后的脚本,我发现问题:您使用的是forwhile

#! /bin/bash

while read LINE ; do
  if [[ $LINE = sendMessage4K* ]]; then
     echo '/*---RUAISI---*/' >> temp2
     echo "$LINE" >> temp2
   elif [[ $LINE =~ *alpha_display\(* ]]; then
     echo "$LINE" >> temp2
     echo '/*---RUAISI---*/' >> temp2
  else
     echo "$LINE" >> temp2
  fi
done < temp1

为避免删除前导空格,请在while

之前添加此行
IFS=$'\n'

答案 2 :(得分:1)

编辑:哎呀,我的回答大多与choroba的那个重复。我要把它留在这里,因为我认为它会更详细地说明事情的原因,但你应该接受choroba的。

你的问题在这里:

for LINE in `(cat temp1)`

这会将每一行拆分为IFS,因此给定一条输入行:

extern void alpha_display

你得到一个类似于这样的for循环:

for LINE in extern void alpha_display; do

这意味着LINE按顺序设置为:

  1. extern
  2. void
  3. alpha_display
  4. 为了证明这一点,请尝试以下小脚本:

    for LINE in `cat temp1`; do
      echo "$LINE"
    done
    

    如果你真的想逐行阅读文件,最好在read循环中使用while,并在源文件中重定向输入。将以下输出与上一个脚本生成的内容进行比较:

    while read LINE; do
      echo "$LINE"
    done < temp1
    

    考虑到这一点,您可以像这样修复脚本:

    while read LINE; do
      if [[ "$LINE" = sendMessage4K* ]]; then
         echo '/*---RUAISI---*/' >> temp2
       elif [[ "$LINE" = *alpha_display\(* ]]; then
         echo '/*---RUAISI---*/' >> temp2
       fi
    
       echo "$LINE" >> temp2
    done < temp1
    

    请注意,除了使用while循环之外,我还从elif表达式中删除了正则表达式运算符(因为,正如之前已经指出的那样,您使用的是glob表达式而不是比正则表达式),我已经删除了一些冗余代码。

    此脚本生成以下输出:

    FIX
    /*---RUAISI---*/
    sendMessage4K(NomRPC,sbuffer,"KP07");
    FIX
    extern void alpha_display(char *loc, long length){
    /*---RUAISI---*/
    FIX
    }
    FIX
    

    因为read实际上仍然在IFS上拆分(然后将它们重新组合在一起),所以最终会丢失前导空格或尾随空格。您可以通过在脚本顶部添加以下内容使IFS仅包含行尾来解决此问题:

    IFS='\n'
    

    我仍然建议bash不一定是这项工作的正确工具。 sedawk可能会更有效。这与awk脚本相同:

    #!/usr/bin/awk
    
    /sendMessage4K/ || /alpha_display\(/ {
        print "/*---RUAISI---*/"
        print
        next
    }
    
    {print}
    

    如果您将其保存在名为“fixit.awk”的文件中,则可以像这样运行:

    awk -f fixit.awk < temp1 > temp2