Это потому, что s1
и s2
работают только как ссылки на ваши объекты. При назначении s2 = s1
вы назначаете только ссылку, что означает, что оба будут указывать на один и тот же объект в памяти (объект, который имеет текущий текст «первым»).
Когда вы сейчас устанавливаете сеттер, на s1 или s2, оба будут изменять один и тот же объект.
Это может сработать для вас (GNU sed):
'sed -n '/category/{:a;N;/done/!ba;x;s/^/x/;/^x\{3\}$/{x;p;q};x}' file
Отключить автоматическую печать с помощью параметра -n
. Соберите линии между category
и done
. Храните счетчик в удержании и когда он достигает 3, напечатайте коллекцию в пространстве шаблонов и закройте.
Или, если вы предпочитаете awk:
awk '/^category/,/^done/{if(++m==1)n++;if(n==3)print;if(/^done/)m=0}' file
awk -v tgt=3 '
/^category$/ { fnd=1; rec="" }
fnd {
rec = rec $0 ORS
if (/^done$/) {
if (++cnt == tgt) {
printf "%s",rec
exit
}
fnd = 0
}
}
' file
Попробуйте сделать это:
awk -v n=3 '/^category/{l++} (l==n){print}' file.txt
Или еще cryptic:
awk -v n=3 '/^category/{l++} l==n' file.txt
Если ваш файл большой:
awk -v n=3 '/^category/{l++} l>n{exit} l==n' file.txt
/^category/
означает строку, начинающуюся с «категории», она действительно отличается от категории , содержащей i>. Поэтому нет необходимости в каких-либо модификациях, сценарий по-прежнему работает AS IS.
– Gilles Quenot
8 November 2012 в 06:16
Если ваш файл не содержит никаких нулевых символов, используйте GNU sed
. Это обнаружит появление третьего диапазона шаблонов. Однако, вы можете легко изменить это, чтобы получить любое событие, которое вы хотели бы.
sed -n '/^category/ { x; s/^/\x0/; /^\x0\{3\}$/ { x; :a; p; /done/q; n; ba }; x }' file.txt
Результаты:
category
3
r
d
done
Объяснение:
Отключить по умолчанию печать с помощью переключателя -n
. Сопоставьте слово «категория» в начале строки. Поменяйте пространство шаблонов пространством удержания и добавьте нулевой символ в начало шаблона. В примере, если шаблон затем содержит два ведущих нулевых символа, вытащите шаблон из пространства пробелов. Теперь создайте цикл и распечатайте содержимое пространства шаблонов до тех пор, пока не будет сопоставлен последний шаблон. Когда этот последний шаблон найден, sed
закроется. Если он не найден, sed
продолжит читать следующую строку ввода и продолжить в своем цикле.
if (prevRec ~ /awk/)
перед печатью.
– Ed Morton
8 November 2012 в 15:30
С помощью GNU awk вы можете установить разделитель записи в регулярное выражение:
<file awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
Выход:
category
3
r
d
done
RT
- разделитель совместимых записей. Обратите внимание, что запись относительно n
будет отключена на единицу, так как первая запись относится к тому, что предшествует первому RS
.
Согласно комментарию Эда, это будет не работают, когда у записей есть другие данные между ними, например:
category
1
s
t
done
category
2
n
d
done
foo
category
3
r
d
done
bar
category
4
t
h
done
. Один из способов обойти это - очистить вход с помощью второго (или первого) awk:
<file awk '/^category$/,/^done$/' |
awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
Выход:
category
3
r
d
done
Поскольку Ed отметил в комментариях, указанные выше методы не ищут окончания шаблон. Один из способов сделать это, который не был рассмотрен другими ответами, - с getline
(обратите внимание, что существуют некоторые оговорки с awk getline):
<file awk '
/^category$/ {
v = $0
while(!/^done$/) {
if(!getline)
exit
v = v ORS $0
}
if(++nr == n)
print v
}' n=3
В одной строке:
<file awk '/^category$/ { v = $0; while(!/^done$/) { if(!getline) exit; v = v ORS $0 } if(++nr == n) print v }' n=3
getline
, которая выполняет поиск done
.
– Thor
10 November 2012 в 15:49
category
иdone
, если нетdone
, это может быть то, что требует пользователь. – potong 8 November 2012 в 17:30