Показать полную графическую версию : Изменение строк в файле
Nikugorsk
07-06-2018, 15:32
Добрый день! Решил усложнить себе жизнь и начать оптимизировать некоторые процессы. Поэтому буду премного благодарен за ответ с комментариями, что где и почему пишем) Задача: в папке сложены Файлы 1, 2, 3... 1000. Формат txt. В этих файлах есть текст. Во всех разный. При этом есть строка (чаще первая) в которой написано «ааа_1#0», где 1 это число которое необходимо оставить, а все остальное надо (что в ковычках) надо удалить. Как это сделать через исполнительный файл, ибо файликов таких очень много??? Количество символов в ковычках всегда разное. Нужная комбинации всегда окружена _ и #
Nikugorsk, упаковываете несколько таких файлов в архив, который прилагаете к сообщению. Дальше смотрим.
Nikugorsk
07-06-2018, 16:42
Nikugorsk, упаковываете несколько таких файлов в архив, который прилагаете к сообщению. Дальше смотрим.
Приложил
Nikugorsk,
нужны файлы с разным содержимым или если знаете неплохо содержимое, есть ли в файле строка(и) с похожим содержимым кроме этой строки: 7,2 "Центр_1664#0", т.е если искать по символу _ или # или обеим или по кавычкам - гарантированно будет найдена только одна эта строка?
И ещё, к словам коллеги: случайно ли то, что искомые цифры в файле совпадают с именем файла?
На WSH:
Option Explicit
Dim strSourceFolder
Dim objFSO
Dim objFile
Dim objRegExp
Dim strContent
If WScript.Arguments.Count = 1 Then
strSourceFolder = WScript.Arguments.Item(0)
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strSourceFolder) Then
Set objRegExp = WScript.CreateObject("VBScript.RegExp")
With objRegExp
.Pattern = "^(.+ "")(?:.+_)(\d+)(?:#)(.+"")$"
.Global = True
.MultiLine = True
End With
For Each objFile In objFSO.GetFolder(strSourceFolder).Files
If StrComp(objFSO.GetExtensionName(objFile.Name), "txt", 0) = 0 Then
With objFSO.OpenTextFile(objFile.Path)
strContent = .ReadAll()
.Close
End With
If objRegExp.Test(strContent) Then
objFSO.CopyFile objFile.Name, objFSO.GetBaseName(objFile.Name) & ".bak", True
With objFSO.CreateTextFile(objFile.Name, True)
.Write objRegExp.Replace(strContent, "$1$2$3")
.Close
End With
Else
' Nothing to do
End If
Else
' Nothing to do
End If
Next
Set objRegExp = Nothing
Else
WScript.Echo "Can't find source folder [" & strSourceFolder & "]."
WScript.Quit 2
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: cscript.exe //nologo """ & WScript.ScriptName & """ <Source folder>"
WScript.Quit 1
End If
WScript.Quit 0
Исходная папка указывается аргументом скрипта (также можно просто перетащить папку на скрипт в Проводнике). Будут обработаны все *.txt файлы из указанной папки. При нахождении шаблона в содержимом текстового файла и последующей замене делается резервная копия исходного файла с расширением .bak.
Согласно изложенным Вами выше правилам поиска и замены в выложенных для примера файлах произойдут следующие замены — в 1657.txt:
11,2 "Центр_1657#0"
на:
11,2 "16570"
и в 1664.txt:
7,2 "Центр_1664#0"
на:
7,2 "16640"
Nikugorsk
07-06-2018, 20:11
Nikugorsk,
нужны файлы с разным содержимым или если знаете неплохо содержимое, есть ли в файле строка(и) с похожим содержимым кроме этой строки: 7,2 "Центр_1664#0", т.е если искать по символу _ или # или обеим или по кавычкам - гарантированно будет найдена только одна эта строка?
Да, гарантированно найдётся только эта строка. По любому из 3х признаков.
На WSH:
Option Explicit
Dim strSourceFolder
Dim objFSO
Dim objFile
Dim objRegExp
Dim strContent
If WScript.Arguments.Count = 1 Then
strSourceFolder = WScript.Arguments.Item(0)
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strSourceFolder) Then
Set objRegExp = WScript.CreateObject("VBScript.RegExp")
With objRegExp
.Pattern = "^(.+ "")(?:.+_)(\d+)(?:#)(.+"")$"
.Global = True
.MultiLine = True
End With
For Each objFile In objFSO.GetFolder(strSourceFolder).Files
If StrComp(objFSO.GetExtensionName(objFile.Name), "txt", 0) = 0 Then
With objFSO.OpenTextFile(objFile.Path)
strContent = .ReadAll()
.Close
End With
If objRegExp.Test(strContent) Then
objFSO.CopyFile objFile.Name, objFSO.GetBaseName(objFile.Name) & ".bak", True
With objFSO.CreateTextFile(objFile.Name, True)
.Write objRegExp.Replace(strContent, "$1$2$3")
.Close
End With
Else
' Nothing to do
End If
Else
' Nothing to do
End If
Next
Set objRegExp = Nothing
Else
WScript.Echo "Can't find source folder [" & strSourceFolder & "]."
WScript.Quit 2
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: cscript.exe //nologo """ & WScript.ScriptName & """ <Source folder>"
WScript.Quit 1
End If
WScript.Quit 0
Исходная папка указывается аргументом скрипта (также можно просто перетащить папку на скрипт в Проводнике). Будут обработаны все *.txt файлы из указанной папки. При нахождении шаблона в содержимом текстового файла и последующей замене делается резервная копия исходного файла с расширением .bak.
Согласно изложенным Вами выше правилам поиска и замены в выложенных для примера файлах произойдут следующие замены — в 1657.txt:
11,2 "Центр_1657#0"
на:
11,2 "16570"
и в 1664.txt:
7,2 "Центр_1664#0"
на:
7,2 "16640"
А как 0 в конце убрать? Должен остаться только 1657 и 1664
И ещё, к словам коллеги: случайно ли то, что искомые цифры в файле совпадают с именем файла?
Это частный случай. Для примера
А как 0 в конце убрать? Должен остаться только 1657 и 1664 »
Тогда замените строку:
.Pattern = "^(.+ "")(?:.+_)(\d+)(?:#)(.+"")$"
на:
.Pattern = "^(.+ "")(?:.+_)(\d+)(?:#.+)("")$"
Это частный случай. Для примера »
Ясно.
Как это сделать через исполнительный файл, ибо файликов таких очень много??? »
powershell
script.ps1
dir *.txt -file|%{
(gc $_.fullname -enc default) -replace '(?<=\")[^_]*_|#[^"]*(?=\")'|`
set-content ($_.fullname) -enc default
}
Для запуска скрипта:
run.bat
@echo off
echo.Поехали
powershell -ex bypass .\script.ps1
echo.Приехали
pause
Nikugorsk
08-06-2018, 07:08
Как это сделать через исполнительный файл, ибо файликов таких очень много??? »
powershell
script.ps1
dir *.txt -file|%{
(gc $_.fullname -enc default) -replace '(?<=\")[^_]*_|#[^"]*(?=\")'|`
set-content ($_.fullname) -enc default
}
Для запуска скрипта:
run.bat
@echo off
echo.Поехали
powershell -ex bypass .\script.ps1
echo.Приехали
pause
Не получается
Не получается »
Если Win XP, то:
dir *.txt|where{!$_.psiscontainer}|%{
(gc $_.fullname) -replace '(?<=\")[^_]*_|#[^"]*(?=\")'|`
set-content ($_.fullname)
}
если новее, то лучше обновить PoSh до актуальной версии...
megaloman
08-06-2018, 16:39
Nikugorsk, Я не проверял код от Iska, уверен, он рабочий.InBox = "Z:\Box_In" ' Папка с файлами
InExt = "txt" ' Расширение файлов для обработки
' --------------------------------
Set WArg = WScript.Arguments
If Not WArg.Count = 0 Then InBox = WArg.Item(0)
Set FSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set InDir = FSO.GetFolder(InBox)
If Err.Number <> 0 Then
MsgBox "Ошибка при открытии " + CStr(Err.Number) + vbCrLf + vbCrLf + InBox + vbCrLf + vbCrLf + Err.Description
WScript.Quit 2
End If
BakBox = InDir + "\" + Replace(Replace(CStr(Now), ":", "-"), "/", ".") + ".bak"
FSO.CreateFolder (BakBox)
If Err.Number <> 0 Then
MsgBox "Ошибка при создании " + CStr(Err.Number) + vbCrLf + vbCrLf + BakBox + vbCrLf + vbCrLf + Err.Description
WScript.Quit 2
End If
On Error GoTo 0
Set AllFiles = InDir.Files
N = 0
For Each iFile In AllFiles ' Цикл по файлам в папке (как вариант решения)
If UCase(FSO.GetExtensionName(iFile)) = UCase(InExt) Then
With FSO.OpenTextFile(iFile, 1, False)
AllTxt = .ReadAll
.Close
End With
Do
i1 = InStr(1, AllTxt, """")
If i1 = 0 Then Exit Do
i2 = InStr(i1, AllTxt, "_")
If i2 = 0 Then Exit Do
i3 = InStr(i2, AllTxt, "#")
If i3 = 0 Then Exit Do
i4 = InStr(i3, AllTxt, """")
If i4 = 0 Then Exit Do
ii = InDir + "\" + iFile.Name
i = FSO.MoveFile(iFile, BakBox + "\" + CStr(iFile.Name))
With FSO.CreateTextFile(ii, True)
.Write Mid(AllTxt, 1, i1) + Mid(AllTxt, i2 + 1, i3 - i2 - 1) + Mid(AllTxt, i4)
.Close
End With
N = N + 1
Loop While False
End If
Next
If N = 0 Then
MsgBox "В папке" + vbCrLf + vbCrLf + InDir + vbCrLf + vbCrLf + "файлы для обработки не найдены"
FSO.DeleteFolder BakBox, True
WScript.Quit 1
Else
Msg = "В папке" + vbCrLf + InDir + vbCrLf + "обработано " + CStr(N) + " файлов"
MsgBox Msg + vbCrLf + vbCrLf + "исходные файлы в папке" + vbCrLf + BakBox
WScript.Quit 0
End If
Здесь исходные файлы, которые нуждаются в обработке, будут помещены в отдельную папку, что позволяет не смешивать обработанные и исходные файлы.
Папку с исходными файлами можно указать явным образом в тексте скрипта, либо указать в аргументе при вызове, также можно просто перетащить папку на скрипт в Проводнике, при этом явное указание папки в коде скрипта будет проигнорировано.
YuS_2, Помнится, WSH в Win XP уже был, и даже для него что-то дополнительно доустанавливать уже не нужно.
Я не проверял код от Iska, уверен, он рабочий. »
Я на это только надеюсь, поскольку работа регулярных выражений очень сильно завязано на предположения о конкретном содержимом искомого :).
YuS_2, Помнится, WSH в Win XP уже был, и даже для него что-то дополнительно доустанавливать уже не нужно. »
Так он же предлагает не WSH, а PoSH.
Помнится, WSH в Win XP уже был, и даже для него что-то дополнительно доустанавливать уже не нужно. »
Это да, powershell в XP надо установить и новее v2.0 туда не впихнуть, но в читабельности и краткости скриптов, а в некоторых случаях и просто функциональных возможностях, это не сравнимые вещи... просто взгляните на код - три командлета (по сути одна строка) делают то, что на wsh выглядит уже достаточно объемно и скорее всего, новичка оттолкнет от изучения...
А вообще, если будет больше вариантов решений той или иной задачи, разве это плохо?
Что из этого разнообразия выбрать, решит сам ТС, да и другим, столкнувшимся с аналогичной проблемой, может пригодиться...
Так он же предлагает не WSH, а PoSH. »
Да, о том и речь, увы, в XP нет предустановленного PoSh
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.