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