Войти

Показать полную графическую версию : [решено] Удаление одной предыдущей строки


Страниц : [1] 2

Freddy1984
15-08-2019, 12:59
Здравствуйте! Подскажите пожалуйста как на cmd или powershell реализовать следующее:

В текстовом файле имеем:

строка
строка
set REV=1.1
VER:1.10.50=(значение меняется)
строка
строка

Надо во всём txt файле найти и удалить одну предыдущую строку перед VER:1.10.50=(значение меняется)
То есть часть строки постоянна VER:1.10.50= и далее после знака ровно, значения меняются.

Другими словами, надо просто удалять одну предыдущую строку, что бы получилось:

строка
строка
VER:1.10.50=(значение меняется)
строка
строка

Iska
15-08-2019, 14:44
Freddy1984, давайте начнём как обычно — Вы упакуете файл в архив и приложите к сообщению.

Freddy1984
15-08-2019, 14:58
Вы упакуете файл в архив и приложите к сообщению. »
прикрепил

Iska
15-08-2019, 16:30
Freddy1984, так может лучше и искать и удалять именно строку с «SetREV=»?

Freddy1984
15-08-2019, 16:47
так может лучше и искать и удалять именно строку с «SetREV=»? »
в том то и дело что нет, в моём случае так не выйдет, так как SetREV= лишний ТОЛЬКО перед VER:1.10.50=
Во всех остальных случаях эти SetREV= не трогать. Так как в этом же текстовом файле есть и другие позиции, при которых должно быть присутствие SetREV=

megaloman
15-08-2019, 17:47
Freddy1984, FileIn = "Z:\Box_Arc\файл\цель.txt"

RegExp = Chr(13) + "?" + Chr(10) + "?" + ".*SetREV=.*" + Chr(13) + "?" + Chr(10) + "?" + "VER:1\.10\.50="
Rep = Chr(13) + Chr(10) + "VER:1.10.50="

With CreateObject("Scripting.FileSystemObject")
On Error Resume Next
With .OpenTextFile(FileIn, 1)
If Err.Number <> 0 Then
MsgBox "Error open file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Err.Number " + CStr(Err.Number) + vbCrLf + Err.Description
WScript.Quit 1
End If
InTxt = .ReadAll
If Err.Number <> 0 Then
MsgBox "Error read file " + vbCrLf + vbCrLf + FileIn + vbCrLf + vbCrLf + "Err.Number " + CStr(Err.Number) + vbCrLf + Err.Description
WScript.Quit 1
End If
.Close
On Error GoTo 0
End With

With CreateObject("VBScript.RegExp")
.Pattern = RegExp
.IgnoreCase = True
.Global = True
If Not .Test(InTxt) Then
MsgBox "no substrings to replace. Reg expression:" + vbCrLf + vbCrLf + """" + RegExp + """"
WScript.Quit 1
End If
Result = .Replace(InTxt, Rep)
End With

With .CreateTextFile(FileIn, True)
.Write Result
.Close
End With

End With

Freddy1984
15-08-2019, 17:50
VBS. »
Я благодарю Вас. А может вы в курсе как на powershell это сделать?

YuS_2
15-08-2019, 19:29
Надо во всём txt файле найти и удалить одну предыдущую строку перед VER:1.10.50=(значение меняется) »
как на powershell это сделать? »
Допустим, что предыдущая строка, это set REV=(значение меняется), тогда код можно написать так:
(gc 'цель.txt' -enc utf8 -raw) -replace 'SetREV[^\n]*\n(?=VER:1\.10\.50=)'|
out-file 'результат.txt' -enc utf8

Если же, предыдущая строка, это любой текст, тогда шаблон регэкспа необходимо будет исправить на такой:
(gc 'цель.txt' -enc utf8 -raw) -replace '(?<=^|\n)[^\n]+\n(?=VER:1\.10\.50=)'|
out-file 'результат.txt' -enc utf8

greg zakharov
15-08-2019, 21:33
С помощью sed:
sed -i "/set rev=.*/Id" input.txt
С помощью pwsh:
(sls 'set rev=.*' -notmatch .\input.txt).line

Freddy1984
15-08-2019, 23:40
Если же, предыдущая строка, это любой текст, тогда шаблон регэкспа необходимо будет исправить на такой: »
Супер! Вопрос закрыт.

Iska
16-08-2019, 13:53
YuS_2, а почему в первом шаблоне именно «[^\n]», а не просто «.», ведь точка и означает «Any except \n (new line)»? Это просто вопрос, ежели что.

в том то и дело что нет, в моём случае так не выйдет, так как SetREV= лишний ТОЛЬКО перед VER:1.10.50=
Во всех остальных случаях эти SetREV= не трогать. Так как в этом же текстовом файле есть и другие позиции, при которых должно быть присутствие SetREV= »
Выйдет. Причём искать следует именно строку, начинающуюся на SetREV=, находящуюся перед строкой, начинающейся на VER:<цифры>.<цифры>.<цифры>=.

YuS_2
16-08-2019, 17:54
а почему в первом шаблоне именно «[^\n]», а не просто «.», ведь точка и означает «Any except \n (new line)»? Это просто вопрос, ежели что. »
Т.к. текст содержит много строк, это более надежный шаблон для захвата одной строки... скажем так, это скорее привычка использовать именно такой вариант, т.к. в программах, которые использую (например, AkelPad), есть настройка поведения захвата символов точкой...
В принципе, можно и так:
(gc 'цель.txt' -enc utf8 -raw) -replace '(?-s)SetREV.*\n(?=VER:1\.10\.50=)'|
out-file 'результат.txt' -enc utf8
- это эквивалент... так что, использование такой конструкции не принципиально.

Freddy1984
17-08-2019, 09:33
Выйдет. Причём искать следует именно строку, начинающуюся на SetREV=, находящуюся перед строкой, начинающейся на VER:<цифры>.<цифры>.<цифры »
ну, в общим то если искать строку именно перед VER:<цифры> и потом её (SetREV) удалять то это согласен, тоже верно.
Но это по факту всё тоже что я описал выше, только вид сбоку :)

Iska
17-08-2019, 20:29
YuS_2, спасибо, Ваша мысль понятна. Только точки я бы-таки заэкранировал.

ну, в общим то если искать строку именно перед VER:<цифры> и потом её (SetREV) удалять то это согласен, тоже верно. »
Не «тоже верно», а именно так надо делать, и именно так и было сделано. В противном случае при повторном запуске кода мы получим удаление совсем не того, что требовалось.

YuS_2
17-08-2019, 21:50
Только точки я бы-таки заэкранировал. »
однозначно! это всё моя спешка помноженная на невнимательность... :(
исправлено.

Freddy1984
26-08-2019, 11:19
Можно ещё вопрос?
Подскажите пожалуйста как сделать дозапись предыдущей строки?
Вроде логично что вместо replace должен быть write. Но что то не выходит..
То есть имеется:
строка
строка
set REV=1.1
VER:1.10.50=(значение меняется)
строка
строка

Если "set REV=1.1" имеется перед "VER:1.10.50=", то пропускаем, а если "set REV=1.1" перед "VER:1.10.50=" отсутствует, то перед "VER:1.10.50=" дописать "set NEW.REV=5.5"

То есть перед дозаписью возможно как то организовать проверку наличия конкретной предыдущей строки? И если строка отсутствует, до дописать своё.

YuS_2
26-08-2019, 20:04
Вроде логично что вместо replace должен быть write. »
может и логично, но неправильно :)
Нет такого оператора в данном контексте...
А код будет примерно таким:
$var = 'Set NEW.REV=5.5'
(gc 'цель.txt' -enc utf8 -raw) -replace '(?<!set rev\=1\.1[^\n]*\n)(ver:1\.10\.50=)',"$var`n`$1" |
out-file 'результат.txt' -enc utf8

YuS_2
27-08-2019, 10:46
думал что скрипт эти записи будет пропускать »
с чего бы вдруг?
Условие было таким:
Если "set REV=1.1" имеется перед "VER:1.10.50=", то пропускаем »
Соответственно, именно так и работает шаблон регулярного выражения, т.е. если перед строкой "VER:1.10.50=" нет строки, содержащей текст "set REV=1.1", то будет добавлена строка, записанная в переменную $var

Freddy1984
27-08-2019, 11:15
с чего бы вдруг? »
да, я разобрался, кое что упустил, прошу прощения :)
Можно тогда ещё один вопрос в догонку? :)
У меня после "$var`n`$1" в строку идёт ещё один replace, но в консоли пишет "Отсутствует выражение после ","
То есть ругается на то что после запятой идут кавычки как я понял. А эти кавычки можно как то заэкранировать? Просто пробовал по разному, но что то не выходит.. Что то типа '"$var`n`$1"'
Запускаю в пакетнике через powershell -c

YuS_2
27-08-2019, 12:20
Запускаю в пакетнике через powershell -c »
запускайте пакетником скрипт
powershell -f '.\script.ps1'
меньше будет проблем




© OSzone.net 2001-2012