Войти

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


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

ul9
23-10-2012, 01:58
Всем привет!
Решила снова прибегнуть к помощи форумчан :)
Попробую описать подробно проблему. Есть папка (test) с файлами и подпапками, содержащими разные файлы. Созданы дополнительно два текстовых файла. Из первого файла берём образец (многострочный текстовый файл), т.е. то, что надо найти в файлах папок test. А второй файл это то, на что нужно заменить найденное. Хотелось бы, чтобы можно было задавать маску поиска (strMask = "*.txt")

ul9
23-10-2012, 02:02
Пробовала с gsar и sed экспериментировать, но что-то не получилось добиться поиска текста из файла-образца.

@echo off
setlocal

set "replace=some text"
sed "s/zamena/%replace%/g" test1.txt 1>test2.txt
если бы можно было задавать путь
set "replace=C:\test\example.txt"

ul9
23-10-2012, 17:15
Нашла ещё вот такой скрипт, но опять-таки заменяет не из текстового файла

[cscript|wscript] replace.vbs Find Replacewith File
Find … Required. Substring being searched for.
Replacewith … Required. Replacement substring.
File … Source and destination file for the replacement


Dim FileName, Find, ReplaceWith, FileContents, dFileContents
Find = WScript.Arguments(0)
ReplaceWith = WScript.Arguments(1)
FileName = WScript.Arguments(2)

'Read source text file
FileContents = GetFile(FileName)

'replace all string In the source file
dFileContents = replace(FileContents, Find, ReplaceWith, 1, -1, 1)

'Compare source And result
if dFileContents <> FileContents Then
'write result If different
WriteFile FileName, dFileContents

Wscript.Echo "Replace done."
If Len(ReplaceWith) <> Len(Find) Then 'Can we count n of replacements?
Wscript.Echo _
( (Len(dFileContents) - Len(FileContents)) / (Len(ReplaceWith)-Len(Find)) ) & _
" replacements."
End If
Else
Wscript.Echo "Searched string Not In the source file"
End If

'Read text file
function GetFile(FileName)
If FileName<>"" Then
Dim FS, FileStream
Set FS = CreateObject("Scripting.FileSystemObject")
on error resume Next
Set FileStream = FS.OpenTextFile(FileName)
GetFile = FileStream.ReadAll
End If
End Function

'Write string As a text file.
function WriteFile(FileName, Contents)
Dim OutStream, FS

on error resume Next
Set FS = CreateObject("Scripting.FileSystemObject")
Set OutStream = FS.OpenTextFile(FileName, 2, True)
OutStream.Write Contents
End Function

Iska
23-10-2012, 18:52
Из первого файла берём образец (многострочный текстовый файл), т.е. то, что надо найти в файлах папок test. А второй файл это то, на что нужно заменить найденное. »
Выложите архив с примером: «первый файл» — что заменять, «второй файл» — на что заменять, и образец файла — где заменять.

ul9
23-10-2012, 19:22
Вот, но это не мой пример. Просто всегда текст (заменяемый) разный и выкладывать конкретный случай не имеет смысла. Я для каждой замены продублирую скрипт со своими заменами. В архиве заменять нужно в фале html, но иногда также приходится заменять и в файлах яваскрипта, не затрагивая html. Поэтому хотелось бы, чтобы можно было выбирать тип файла (html, js..)

Iska
23-10-2012, 22:51
ul9, тип файла не важен. Важна кодировка. Особенно желательно, чтобы она совпадала у тех файлов, в которых ищем, так и у тех файлов, которые используются в качестве источников фрагментов поиска и замены. В приведённом Вами примере это не так: «work.htm» имеет кодировку windows-1251, а «Найти это.txt» и «заменить этим.txt» — UTF-8, да ещё и без BOM. Что, при наличии во фрагменте поиска кирилицы в приведённом примере делает невозможным простой поиск и замену.

Что скажете?

ul9
23-10-2012, 23:01
Всё поняла. Все файлы будут в UTF-8 без BOM.
«Найти это.txt» и «заменить этим.txt» тоже сохраню в нужной кодировке, так как они делаются руками. А вот файлы, в которых нужно работать, приходят в UTF-8 без BOM.
И я ещё хотела бы уточнить, возможен будет такой вариант, чтобы при пустом файле «заменить этим.txt» в файле «work.htm» просто удалялся фрагмент кода, заданный в «Найти это.txt»?

Iska
23-10-2012, 23:06
Всё поняла. Все файлы будут в UTF-8 без BOM.
«Найти это.txt» и «заменить этим.txt» тоже сохраню в нужной кодировке, так как они делаются руками. А вот файлы, в которых нужно работать, приходят в UTF-8 без BOM. »
Ясно.

И я ещё хотела бы уточнить, возможен будет такой вариант, чтобы при пустом файле «заменить этим.txt» в файле «work.htm» просто удалялся фрагмент кода, заданный в «Найти это.txt»? »
Да.

Как осуществляем замену: переписываем содержимое файла новым содержимым (с произведённой заменой) поверх, без резервной копии, так?

ul9
23-10-2012, 23:10
Как осуществляем замену: переписываем содержимое файла новым содержимым (с произведённой заменой) поверх, без резервной копии, так? »
В резервной копии нет необходимости. Меняем безоговорочно и безвозвратно :)

Iska
23-10-2012, 23:54
Ну, вот, в первом приближении:
Option Explicit

Const ForReading = 1
Const ForWriting = 2


Dim objArgs
Dim objFSO
Dim objFile

Dim strWhatFind
Dim strReplaceBy

Dim strContent


Set objArgs = WScript.Arguments.Named

If objArgs.Count = 4 Then
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

If objArgs.Exists("FolderForScan") Then
If objArgs.Exists("FileExtension") Then
If objArgs.Exists("FileWhatFind") Then
If objArgs.Exists("FileReplaceBy") Then
If objFSO.FolderExists(objArgs.Item("FolderForScan")) Then
If objFSO.FileExists(objArgs.Item("FileWhatFind")) Then
If objFSO.FileExists(objArgs.Item("FileReplaceBy")) Then
If objFSO.GetFile(objArgs.Item("FileWhatFind")).Size > 0 Then
With objFSO.OpenTextFile(objArgs.Item("FileWhatFind"), ForReading)
strWhatFind = .ReadAll()
.Close
End With

If objFSO.GetFile(objArgs.Item("FileReplaceBy")).Size > 0 Then
With objFSO.OpenTextFile(objArgs.Item("FileReplaceBy"), ForReading)
strReplaceBy = .ReadAll()
.Close
End With
Else
strReplaceBy = ""
End If

WScript.Echo "Folder for scan: " & objArgs.Item("FolderForScan")
WScript.Echo "File extension: " & objArgs.Item("FileExtension")
WScript.Echo "File what find: " & objArgs.Item("FileWhatFind")
WScript.Echo "File replace by: " & objArgs.Item("FileReplaceBy")
WScript.Echo

ScanSubFolders objFSO.GetFolder(objArgs.Item("FolderForScan"))
Else
WScript.Echo "File [" & objArgs.Item("FileWhatFind") & "] is zero length"
End If
Else
WScript.Echo "File [" & objArgs.Item("FileWhatFind") & "] not found"
End If
Else
WScript.Echo "File [" & objArgs.Item("FileWhatFind") & "] not found"
End If
Else
WScript.Echo "Folder [" & objArgs.Item("FolderForScan") & "] not found"
End If
Else
WScript.Echo "Not found argument <FileReplaceBy>"
Call Usage
End If
Else
WScript.Echo "Not found argument <FileWhatFind>"
Call Usage
End If
Else
WScript.Echo "Not found argument <FileExtension>"
Call Usage
End If
Else
WScript.Echo "Not found argument <FolderForScan>"
Call Usage
End If

Set objFSO = Nothing
Else
Call Usage
End If

Set objArgs = Nothing

WScript.Quit
'=============================================================================

'=============================================================================
Sub ScanSubFolders(objFolder)
Dim objSubFolder
Dim objFile

WScript.Echo "[" & objFolder.Path & "]"

For Each objFile In objFolder.Files
If UCase(objFSO.GetExtensionName(objFile.Name)) = UCase(objArgs.Item("FileExtension")) Then
WScript.Echo " " & objFile.Name

If objFile.Size > 0 Then
With objFSO.OpenTextFile(objFile.Path, ForReading)
strContent = .ReadAll()
.Close
End With

If InStr(1, strContent, strWhatFind, vbTextCompare) > 0 Then
WScript.Echo " Fragment for replace found"

With objFSO.OpenTextFile(objFile.Path, ForWriting)
.Write Replace(strContent, strWhatFind, strReplaceBy)
.Close
End With
End If
End If
End If
Next

WScript.Echo

For Each objSubFolder In objFolder.SubFolders
ScanSubFolders objSubFolder
Next
End Sub
'=============================================================================

'=============================================================================
Sub Usage()
WScript.Echo "Usage: cscript.exe //nologo " & WScript.ScriptName & " " & _
"/FolderForScan:<folder> " & _
"/FileExtension:<extension> " & _
"/FileWhatFind:<file> " & _
"/FileReplaceBy:<file>"
End Sub
'=============================================================================

ul9
24-10-2012, 00:05
Спасибо Вам. А как его использовать? Приведите пожалуйста пример.

Sub Usage()
WScript.Echo "Usage: cscript.exe //nologo " & WScript.ScriptName & " " & _
"/FolderForScan:<folder> " & _
"/FileExtension:<extension> " & _
"/FileWhatFind:<file> " & _
"/FileReplaceBy:<file>"
End Sub

Iska
24-10-2012, 00:41
А как его использовать? »
Если его запустить — он напишет, как:
cscript.exe //nologo Script.vbs /FolderForScan:<folder> /FileExtension:<extension> /FileWhatFind:<file> /FileReplaceBy:<file>

Приведите пожалуйста пример. »
Пример:
cscript.exe //nologo "c:\My Scripts\Script.vbs" /FolderForScan:"E:\Песочница\0192" /FileExtension:"htm" /FileWhatFind:"E:\Песочница\0191\Найти это.txt" /FileReplaceBy:"E:\Песочница\0191\заменить этим.txt"
Естественно, для текущего каталога указывать пути не обязательно, равно как и заключать пути в кавычки, если в них нет пробельных символов. Если Вы не используете что-либо наподобие Far Manager'а — проще всего вписать это в пакетный файл.

ul9
24-10-2012, 01:09
А он почему-то в подпапках не ищет... Может я что-то не так делаю.

Всё, разобралась. Причина была в путях. Всё работает отлично. Большое спасибо!

ul9
26-10-2012, 05:18
Iska, очень уж ваш скрипт хорош и удобен!
Я хотела бы ещё спросить у вас. Возможно ли задать условие для запуска нужного кода?
cscript.exe //nologo "c:\My Scripts\Script.vbs" /FolderForScan:"E:\Песочница\0192" /FileExtension:"htm" /FileWhatFind:"E:\Песочница\0191\Найти это.txt" /FileReplaceBy:"E:\Песочница\0191\заменить этим.txt"

Запускаем скрипт и появляется msgbox с кнопками 1, 2, 3
В зависимости от того, какую нажали происходит выполнение нужного куска кода.

if 1
cscript.exe //nologo "c:\My Scripts\Script.vbs" /FolderForScan:"E:\Песочница\0001" /FileExtension:"htm" /FileWhatFind:"E:\Песочница\01\Найти это.txt" /FileReplaceBy:"E:\Песочница\01\заменить этим.txt"

if 2
cscript.exe //nologo "c:\My Scripts\Script.vbs" /FolderForScan:"E:\Песочница\0002" /FileExtension:"htm" /FileWhatFind:"E:\Песочница\02\Найти это.txt" /FileReplaceBy:"E:\Песочница\02\заменить этим.txt"

if 3
cscript.exe //nologo "c:\My Scripts\Script.vbs" /FolderForScan:"E:\Песочница\0003" /FileExtension:"htm" /FileWhatFind:"E:\Песочница\03\Найти это.txt" /FileReplaceBy:"E:\Песочница\03\заменить этим.txt"


Конечно можно создать три батника и запускать каждый, в зависимости от нужды. Но может есть более элегантное решение :)

Iska
26-10-2012, 07:14
Конечно можно создать три батника и запускать каждый, в зависимости от нужды. Но может есть более элегантное решение »
Это вполне нормальное решение для повторного использования кода. Аналогичного результата можно добиться создав три ярлыка с соответствующей командной строкой в каждом.

ul9
26-10-2012, 15:18
Это вполне нормальное решение для повторного использования кода. Аналогичного результата можно добиться создав три ярлыка с соответствующей командной строкой в каждом. »
На самом деле их значительно больше (около 15). Не хотелось бы на рабочем столе выстраивать их все в ряд :)

Iska
26-10-2012, 17:30
Создайте папку на Рабочем столе, в Главном меню, создайте панель на Панели задач. Туда и поместите ярлыки или пакетные файлы.

ul9
26-10-2012, 19:42
А через msgBox условие возможно реализовать или там только yes и no?

Iska
26-10-2012, 20:47
А через msgBox условие возможно реализовать или там только yes и no? »
Доступно максимум три кнопки, коллега.

ul9
26-10-2012, 21:00
Доступно максимум три кнопки, коллега. »
А если в cmd вывести?

echo 1 - green
echo 2 - red
и т.д.

Вводишь число и запускается скрипт. Я бы сама написала, но как эти условия задать без понятия, да ещё и связать с кнопками. Имею только общие представления по аналогии с яваскриптом.




© OSzone.net 2001-2012