У меня есть файл со следующими строками. Я могу отфильтровать конкретное слово и отобразить строки под / над ним. Однако я также хотел удалить его в исходном файле и добавить в новый файл.
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
Я могу сделать это с помощью: grep -i green origfile -A1 -B1 >> newfile, но как удалить его из файла ориг.
origfile:
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
новый файл:
<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>
Есть ли более чистый / быстрый способ сделать это?
@kevinnls -C1, а?
ой. да -C1. спасибо @BenjaminW.





Вы можете сделать это на одном awk, разделяя записи по разным файлам. Это будет искать слово green и помещать одну строку до и после него и выводить его в новый файл вместе с удалением из исходного файла.
awk '
FNR==NR{
if ($0~/green/){
words[FNR]
}
next
}
((FNR+1) in words) || (FNR in words) || ((FNR-1) in words){
print > "newfile"
next
}
1
' Input_file Input_file > temp && mv temp Input_file
Объяснение: Добавление подробного объяснения приведенного выше кода.
awk ' ##Starting awk program from here.
FNR==NR{ ##Checking condition FNR==NR which will be TRUE when first time Input_file is being read.
if ($0~/green/){ ##Checking condition if line contains green string then do following.
words[FNR] ##Creating array of words with index of current line number.
}
next ##next will skip all further statements from here.
}
((FNR+1) in words) || (FNR in words) || ((FNR-1) in words){
##Checking condition if current line+1 OR current line OR current line-1 numbers are in words array then do following.
print > "newfile" ##Printing current line into newfile output file.
next ##next will skip all further statements from here.
}
1 ##Printing current line here.
' Input_file Input_file > temp && mv temp Input_file
##Mentioning Input_file(s) and doing inplace save into it.
[не OP]: не могли бы вы подробнее рассказать, как это работает? (просто хочу научиться)
@kevinnls, да, я сейчас пишу подробное объяснение, пожалуйста, дайте мне несколько минут :)
@kevinnls, теперь в мой ответ добавлено подробное объяснение, ура.
@ RavinderSingh13, я пробовал, но он все еще (зеленый) в исходном файле.
@gafm, извините, произошла опечатка, попробуйте мой отредактированный код один раз, он должен слететь, дайте мне знать, как это происходит, ура.
работает как шарм. спасибо @ RavinderSingh13 :)
@gafm, добро пожаловать, ура и приятного обучения :)
Вот решение ed.
#!/usr/bin/env bash
ed -s origfile.txt <<-EOF
/<td>green</td>/;?^<tr>?;/^</tr>/w newfile.txt
.;/^</tr>/d
w
q
EOF
Или отдельный скрипт ed, просто назовите script.ed
/<td>green</td>/;?^<tr>?;/^</tr>/w newfile.txt
.;/^</tr>/d
w
q
потом
ed -s origfile.txt < script.ed
$ cat tst.awk
$0 == "<tr>" { inRow=1; row=$0; next }
inRow {
row = row ORS $0
if ( $0 == "</tr>" ) {
inRow = 0
if ( index(row,"<td>green</td>") ) {
print row | "cat>&2"
next
}
else {
$0 = row
}
}
}
!inRow
$ awk -f tst.awk file >o1 2>o2
$ head o?
==> o1 <==
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
==> o2 <==
<tr>
<td>tree</td><td>apple</td><td>green</td>
</tr>
Чтобы изменить исходный файл:
$ awk -f tst.awk file >o1 2>o2 && mv o1 file
$ cat file
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
<tr>
<td>tree</td><td>apple</td><td>red</td>
</tr>
не имеет отношения к вашему вопросу, но вы можете использовать
-C2вместо-A1 -B1. просто подумал, что поделюсь