Найти соответствующий текст в последовательных строках и увеличить числовое значение в следующей строке

Что бы это ни стоило, мне нужно делать это довольно часто, и я никогда не могу вспомнить точный способ использования while IFS= read..., поэтому я определил следующую функцию в своем профиле bash:

# iterate the line of a file and call input function
iterlines() {
    (( $# < 2 )) && { echo "Usage: iterlines <File> <Callback>"; return; }
    local File=$1
    local Func=$2
    n=$(cat "$File" | wc -l)
    for (( i=1; i<=n; i++ )); do
        "$Func" "$(sed "${i}q;d" "$File")"
    done
}

Эта функция сначала определяет количество строк в файле, затем использует sedдля извлечения строки за строкой и передает каждую строку как один строковый аргумент любой заданной функции. Я предполагаю, что это может стать действительно неэффективным с большими файлами, но это не было проблемой для меня до сих пор (предложения о том, как улучшить это приветствие, конечно ).

Использование довольно приятное ИМО:

>> cat example.txt # note the use of spaces, whitespace, etc.
a/path

This is a sentence.
"wi\th quotes"
$End
>> iterlines example.txt echo # preserves quotes, $ and whitespace
a/path

This is a sentence.
"wi\th quotes"
$End
>> x() { echo "$#"; }; iterlines example.txt x # line always passed as single input string
1
1 
1
1
1
1
08.12.2020, 07:40
3 ответа

Используйте awkи установите RS=в пустую строку, чтобы включить обработку входного файла в режиме абзаца:

awk -v RS= -F'\n' '$1 ~ /^ *Name2:$/ && $2 ~ /^ *version: \*abc-xyz-0-196$/ {
    bakline=$0; sub(/.*ID:/,""); newId=$0+1; 
    $0=bakline"\n"; sub(/ID: [0-9]+/,"ID: " newId);
}1' infile

проверка первой и второй строки на соответствие тому, что нам нужно; резервное копирование из совпадающего блока, удаление всего до ID:и увеличение остальных строк в принудительном числовом значении, возврат обратно блока из переменной резервного копирования, затем замена идентификатора значением newId.

0
18.03.2021, 22:44

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

awk '$1=="Name2:",(!NF) {
  if ($2=="*abc-xyz-0-196") f++
  if ($1 == "ID:" && f) sub(/[0-9]+/, $2+1)
  if (!NF) f=0
}1' file
0
18.03.2021, 22:44
perl -00pe 's/Name2:\s*version: \*abc-xyz-0-196\s*ID: \K(\d+)/$1+1/e' ex

Где:

  • perl -00pe...--> для каждого входного абзаца выполните ...и напечатайте
  • s/.../exp/e--> заменить ...на результатeval exp
  • /...1\K...2/--> взять ...1как левый контекст, заменить шину просто...2
0
18.03.2021, 22:44

Теги

Похожие вопросы