Добавление строки с текстом между шаблоном и следующим вхождением того же шаблона в bash - PullRequest
2 голосов
/ 07 февраля 2011

Я пишу bash-скрипт, который изменяет файл, который выглядит следующим образом:

--- usr1 ---<br> data data data data<br> data data data data<br> data data data data<br> --- usr2 ---<br> data data data data<br> data data data data<br> --- usr3 ---<br> data data data data<br> --- endline ---

Один вопрос: как добавить следующую строку пользователя --- usrn --- после последних строк данных пользователя? Второй: Как удалить определенные строки пользовательских данных (строки данных и --- userx ---), т.е. я хотел бы удалить usr2 со всем его набором данных.

Он должен работать на bash 2.05 :), и я думаю, что он будет использовать awk или sed, но я не уверен.
Немного отредактируйте здесь: На самом деле имена пользователей не нумеруются. Мы не знаем, что придут пользователи. Мы только знаем, что имя будет внутри --- pattern

Ответы [ 3 ]

1 голос
/ 07 февраля 2011

Имя пользователя в переменной:

username="kasper"

Удалить пользовательский раздел:

sed "/$username/{:a;N;/\n--- [^[:blank:]]* ---\$/{s/.*\n//;b};ba}" inputfile

или для некоторых версий sed ( отредактировано ):

sed -e "/$username/{" -e ':a' -e 'N' -e '/\n--- [^[:blank:]]* ---$/{s/.*\n//' -e 'b' -e '}' -e 'ba' -e '}' inputfile

Редактировать: возможный вариант для размещения начальных и конечных пробелов:

sed -e "/$username/{" -e ':a' -e 'N' -e '/\n[[:blank:]]*---[[:blank:]]*[^[:blank:]]*[[:blank:]]*---[[:blank:]]*$/{s/.*\n//' -e 'b' -e '}' -e 'ba' -e '}' inputfile

Добавить следующий раздел пользователя:

sed "s/--- end/--- $username ---\ndata data data data\ndata data data data\n&/"

или

sed "/--- end/i--- $username ---\ndatadata data data\ndata data data data\n"

Если ваша версия sed поддерживает изменения на месте, вы можете сделать:

sed -i ...

В противном случае вам придется использовать временный файл:

sed ... inputfile > tmpfile && mv tmpfile inputfile

Лучше всего использовать утилиту типа mktemp или tempfile для создания временного файла и использовать предоставленное имя.

0 голосов
/ 07 февраля 2011

Решение awk для 2-й части:

awk -v del="usr2" 'match($0,/^--- (.*) ---$/,a) {p = (a[1] != del)} p'

Это отключает флаг p, если голова соответствует удаляемому пользователю, иначе он печатает каждую строку.

0 голосов
/ 07 февраля 2011

Обычная оболочка может справиться с этим

Обновлен ответ, включающий второе требование ...

#!/bin/sh

NEWUSER='John Doe'
NEWUSERDATA='how now brown cow'
REMOVEUSER='usr2'

state=COPY
while read x; do
  case "$state/$x" in
    *"/--- endline ---")
      echo --- $NEWUSER ---
      echo "$NEWUSERDATA"
      state=COPY
      ;;
    COPY/*)
      if [ "$x" == "--- $REMOVEUSER ---" ]; then
        state=REMOVE
      fi
      ;;
    REMOVE/---*)
      state=COPY
      ;;
  esac
  if [ $state != REMOVE ]; then
    echo "$x"
  fi
done

Использование это что-то вроде: sh newuser.sh < usertable.txt > newusertable.txt

Кстати, существует альтернативный стиль написания сценариев оболочки, который я мог бы назвать форматом "gnu configure". В «альтернативном стиле» основной цикл будет:

while read x; do
  case "$state/$x" in
    *"/--- endline ---")
      echo --- $NEWUSER ---
      echo "$NEWUSERDATA"
      state=COPY;;
    COPY/*)
      [ "$x" == "--- $REMOVEUSER ---" ] && state=REMOVE;;
    REMOVE/---*)
      state=COPY;;
  esac
  [ $state != REMOVE ] && echo "$x"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...