если выражение регулярное или плохое эхо?(Баш 3.0) - PullRequest
0 голосов
/ 07 декабря 2011

Может кто-нибудь сказать мне, почему это происходит?я пытаюсь вставить несколько строк до появления данной строки, скажем ...

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

, очевидно, лидирующий оператор if работает нормально перед elif.

Я попробовал все варианты цитат и регулярных выражений, которые я могу себе представить ...

любая помощь будет высоко ценится

РЕДАКТИРОВАТЬ: это фактический скрипт, который я использую

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

1 голос
/ 07 декабря 2011

Вы используете оператор сопоставления регулярного выражения = ~, но с правой стороны от него нет регулярного выражения, а есть символ подстановки оболочки.Поэтому измените его на

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

или

[[ $LINE =~ hello_dude\( ]]

, т. Е. Используйте подстановочный знак с соответствующим оператором или регулярное выражение с соответствующим оператором.

Обновление: Глядя на обновленный скрипт, я вижу проблему: вы используете for, где вы должны использовать while:

#! /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'
1 голос
/ 07 декабря 2011

РЕДАКТИРОВАТЬ : Ой, мой ответ в основном дублирует ответ Чороба. Я собираюсь оставить это здесь, потому что я думаю, что в нем будет немного больше подробностей о причинах, но вы, вероятно, должны принять Чоробу.

Ваша проблема здесь:

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

Чтобы продемонстрировать это, попробуйте следующий маленький скрипт:

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

Если вы действительно хотите читать файл построчно, лучше использовать read в цикле while с вводом, перенаправленным из вашего файла souce. Сравните вывод следующего с тем, что производит предыдущий скрипт:

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 (поскольку, как уже указывалось, вы использовали глобальные выражения, а не регулярные выражения) и я удалил некоторый избыточный код.

Этот скрипт выдает следующий вывод:

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

Поскольку read на самом деле все еще разделяет вещи в IFS (а затем соединяет их вместе), вы теряете пробелы в начале или в конце. Это можно исправить, добавив в IFS только конец строки, добавив в начало сценария следующее:

IFS='\n'

Я бы все же предположил, что bash не обязательно является подходящим инструментом для этой работы. sed или awk, вероятно, будет более эффективным. Вот то же самое, что и скрипт awk:

#!/usr/bin/awk

/sendMessage4K/ || /alpha_display\(/ {
    print "/*---RUAISI---*/"
    print
    next
}

{print}

Если вы сохранили это в файле с именем "fixit.awk", вы бы запустили его так:

awk -f fixit.awk < temp1 > temp2
1 голос
/ 07 декабря 2011

Не увидев ваш сценарий, мы не сможем вам в этом помочь. Однако проблема такого рода - вставка строки текста перед конкретным шаблоном соответствия - часто обрабатывается с помощью sed. Например, если у меня есть файл, который выглядит так:

one
two
three

И я хочу вставить «Бананы» перед «двумя», я бы сделал что-то вроде этого:

sed '/ two / i \ Bananas'

Что дает мне:

one
Bananas
two
three

Предполагается, что GNU sed (хотя он будет работать с незначительными изменениями и для других версий sed).

...