Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Удалить в текстовом файле все строки кроме одной нужной. (http://forum.oszone.net/showthread.php?t=347358)

9119 16-12-2020 16:11 2943140

Удалить в текстовом файле все строки кроме одной нужной.
 
Вложений: 1
Добрый.

Есть однотипные файлы txt. В них строка №2. Очень длинная. Явно превышающая стандартное ограничение.
find и findstr пишут "длинная строка"
txt во вложении.

Начинается нужная строка всегда с "audioContent".


Нужно:

1) скопировать строку №2 из source.txt в out.txt.

или

в source.txt удалить ВСЕ строки кроме №2.

В идеале, нужно решение без привязки к искомым словам, а просто к номеру строк.


2) В результирующем txt удалить пробелы, слово "audioContent" и (")двойные кавычки(")

greg zakharov 16-12-2020 18:46 2943166

Берём в руки sed, и:
Код:

sed -i.bak "2!d" *.txt
Удалит всё, за исключением второй строки в txt файлах текущего каталога (с созданием резервных копий оригиналов).
sed не является штатным средством, однако есть много различных портов под винду.

Vadikan 16-12-2020 22:15 2943194

Powershell
Код:

$c = Get-Content -Path "C:\temp\source.txt"
($c[1].split(':')[1].split('"').split(',')).trim() -ne "" | Out-File C:\temp\out.txt


Foreigner 16-12-2020 23:03 2943203

Конкретно для этого файла.
Код:

(Get-Content .\source.txt | ConvertFrom-Json).audioContent | Set-Content out.txt

Vadikan 16-12-2020 23:08 2943205

Foreigner, надо же, только сегодня написал в канале про ConvertFrom-Json и тут же не увидел его :)

9119 16-12-2020 23:09 2943206

Цитата:

Цитата greg zakharov
Удалит всё, за исключением второй строки »

а если скажем нужно удалить 2 и 3 строки... как тогда будет выглядеть команда для sed?



Цитата:

Цитата Vadikan
Powershell »

есть также файл text.json вида:
Скрытый текст
{
"audioConfig": {
"audioEncoding": "LINEAR16",
"pitch": 0,
"speakingRate": 1
},
"input": {
"text": "Тест речевого движка"
},
"voice": {
"languageCode": "ru-RU",
"name": "ru-RU-Wavenet-B"
}
}


Можно ли реализовать замену Тест речевого движка на любую другую фразу (длинную и с символами) в этом файле посредством cmd/powershell/стороннего софта?
В идеале, чтобы после ввода нового текста (до того как он заменит собой Тест речевого движка) он как бы становился в одну строку...без пробелов между строками, абзацев и тд. (как если вы, например, скопируете содержимое любой +/- интернет-статьи и вставите скажем в адресную строку браузера хром, а потом скопируете от туда..там автоматом весь текст делается в 1 строку.)
Привязаться можно разве что к "text": , т.к другие параметры могут быть измененены/смещены и т.д. (в т.ч и Тест речевого движка)

Удалить, например в text.json нужную строку по номеру (как с sed) и вместо нее вставить нужную - не выйдет, т.к номер строки с ""text":" может меняться.

Iska 16-12-2020 23:21 2943209

9119, можно. Только желателен сам файл, целиком, именно в виде файла. Ибо: кодировка, BOM, вид концов строк.

«Привязываться» в json, как и в любом другом структурированном файле, нужно по пути, а не «найти текст-заменить».

Цитата:

Цитата Vadikan
Foreigner, надо же, только сегодня написал в канале про ConvertFrom-Json и тут же не увидел его :) »

Vadikan, бывает :).

9119 16-12-2020 23:31 2943211

Вложений: 1
Прикрепил.

Foreigner 16-12-2020 23:45 2943213

Не совсем понятно зачем удалять строки. Json можно изменить:
Код:

$json = Get-Content text.json | ConvertFrom-Json
$json.input.text = "Новый текст"
$json | ConvertTo-Json | Set-Content new.json


9119 17-12-2020 00:01 2943214

Цитата:

Цитата Foreigner
Json можно изменить »

я этого не знал. Это правда проще.

Я так понял это powershell.
Тогда, если можно, немного уточну задачу..


1) $json = Get-Content text.json | ConvertFrom-Json
2) здесь нужно вывести окно с запросом о вводе текста (при вводе текста задается значение переменной). Не обязательно отдельным окном, но желательно.
Скрипт при этом останавливается, пока не введем нужный текст.

3) $json.input.text = "переменная"
4) $json | ConvertTo-Json | Set-Content new.json


Простите что так на пальцах...

Foreigner 17-12-2020 00:11 2943215

Цитата:

Цитата 9119
2) здесь нужно вывести окно с запросом о вводе текста и задать переменную »

Рисовать окошко? Может как-то попроще, например брать текст из файла или вставлять из буфера обмена? Например:

Код:

$json.input.text = Get-Clipboard
Т.е. скопировал нужный текст в буфер и запустил скрипт.
PS. Если несколько строк, и это не поддерживается речевым движком, то можно их сконвертировать в одну строку:
Код:

$json.input.text = Get-Clipboard | Out-String

9119 17-12-2020 00:26 2943216

Цитата:

Цитата Foreigner
или вставлять из буфера обмена »

идея хорошая, но бывает что нет возможности скопировать сразу весь текст...
и скажем нажимешь сtrl+с 2-3 раза... тогда такой вариант как я понимаю не подходит...

Как будет выглядить вставка из файла?

p.s. можно и без рисования окошка...
достаточно чтобы скрипт стал на паузу и запросил ввод текста (чтоб можно было текст несколько раз копирнуть в данный сркипт.)

Foreigner 17-12-2020 00:34 2943217

Цитата:

Цитата 9119
Как будет выглядить вставка из файла? »

Код:

$text = Get-Content file.txt
$json.input.text = $text


Iska 17-12-2020 00:39 2943218

Foreigner, можно совместить оба подхода — подставлять в тамошний InputBox default'ом значение из Буфера обмена. Тут тебе и возжожность визуального контроля, и возможность ручной коррекции — невеликая плата за лишнее нажатие Enter.

9119 17-12-2020 00:43 2943219

Цитата:

Цитата Iska
можно совместить оба подхода »

как это выглядит в powershell?

Vadikan 17-12-2020 00:53 2943220

Мне кажется надо просто параметр к скрипту добавить. Зачем останавливать скрипт и ждать ввода, указывайте сразу.

Выглядит как-то так http://forum.oszone.net/post-2942327.html#post2942327

9119 17-12-2020 00:59 2943221

Цитата:

Цитата Vadikan
Зачем останавливать скрипт и ждать ввод »

в этом вся суть.... нужно разный текст постоянно менять, каждый раз менять в скрипте - не вариант, как впринципе и в отдельном файле (лишние движения в ввиде ctrl-v, ctrl-s ).
Тут как раз надо чтоб копировать из буфера, с возможностью корректировки на лету так сказать, не лазя по доп файлам...

Iska 17-12-2020 01:08 2943222

Цитата:

Цитата 9119
как это выглядит в powershell? »

Если без особых изысков, то наподобие:
Код:

Add-Type -AssemblyName 'Microsoft.VisualBasic'

$sValue = [Microsoft.VisualBasic.Interaction]::InputBox('Enter value:', 'Enter value', (Get-Clipboard -Format Text))
$sValue

Это уже, конечно, не совсем чистый PoSH. А так-то можно хоть цельный диалог нарисовать, с подкидным дураком и блудницами: Создание настраиваемого поля ввода - PowerShell | Microsoft Docs.

9119 17-12-2020 01:13 2943223

Цитата:

Цитата Iska
Если без особых изысков »

как это совместить с вариантом предложенным на предыдущей странице?
Код:

$json = Get-Content text.json | ConvertFrom-Json
$json.input.text = "Новый текст"
$json | ConvertTo-Json | Set-Content new.json


Iska 17-12-2020 01:18 2943224

Не проверялось:
Код:

Add-Type -AssemblyName 'Microsoft.VisualBasic'

$json = Get-Content text.json | ConvertFrom-Json
$json.input.text = [Microsoft.VisualBasic.Interaction]::InputBox('Enter value for node [json.input.text]:', 'Enter value', (Get-Clipboard -Format Text))
$json | ConvertTo-Json | Set-Content new.json


9119 17-12-2020 01:38 2943225

Цитата:

Цитата Iska
Не проверялось »

да, это похоже то, что нужно... работает. и текст в одну строку переводится, без пробелов.
Окно только под себя настрою, дабы текст можно было удобнее редактировать.

YuS_2 17-12-2020 07:58 2943236

Iska, можно проще поступить (без окон) и бейсик не привлекать:

Цитата:

Цитата 9119
как это совместить с вариантом предложенным на предыдущей странице? »

Цитата:

Цитата 9119
достаточно чтобы скрипт стал на паузу и запросил ввод текста »

Код:

$json = Get-Content text.json | ConvertFrom-Json
$json.input.text = read-host "Пожалуйста, введите или вставьте из буфера текст"
$json | ConvertTo-Json | Set-Content new.json


Iska 17-12-2020 08:19 2943239

YuS_2, не то. Из-под консоли — Read-Host консольный будет, плюс лишнее действие нужно.

9119 17-12-2020 10:42 2943266

Цитата:

Цитата 9119
работает. и текст в одну строку переводится, без пробелов »

заметил, что если запускать скрипт с текстом в буфере (скажем 5000 символов), то весь текст уже в поле ввода (что, к слову очень удобно)...
Но если при этом стать в это поле, и нажать "вставить", вставляется только малое количество текста (500-1000 символов)
По умолчанию какое-то ограничение на кол-во символов для InputBox?

YuS_2 17-12-2020 11:34 2943274

Цитата:

Цитата Iska
Из-под консоли — Read-Host консольный будет, плюс лишнее действие нужно. »

Почему не то? Вроде, как раз, это и требовалось... там я процитировал. Окно никаких преимуществ, всё равно, не даст ведь.
А какое лишнее действие? Ровно столько же, как и в окне.

9119 17-12-2020 13:14 2943287

Цитата:

Цитата YuS_2
Вроде, как раз, это и требовалось »

нужны были разные варианты, но предпочтительнее все таки окно отдельное.
Планирую в нем сделать листбоксы и для настройки других параметров в text.json.



Помогите разобраться с вводом текста в поле, пож.
Пример: копируем из статьи 3 абзаца. Между абзацами - пустые строки (1-3 пустых строки).
Вставляем в поле - вставляется только первый абзац, т.е все символы до первой пустой строки.

Если предварительно сделать все 3 абзаца в 1 строку - то в поле вставляется весь текст.
1) Как-то можно побороть такое неудобство, чтобы не нужно было каждый раз в 1 строку все делать, чтобы это было автоматом при вставке?

2) Поле для ввода текста очень узкое (в 1 строку буквально). Когда вставляешь туда много текста - редактировать его там очень неудобно.
Хотелось бы иметь 8-10 строк высоты.. в идеале с возможностью скрола.
Пробовал задавать ширину и высоту поля ввода. Ширина тянется, а вот высота - нет.

Вот так, на сейчас, окно выглядит
$p='E:\11\bin'
$json = Get-Content $p\text.json | ConvertFrom-Json

Add-Type -assembly System.Windows.Forms

$main_form = New-Object System.Windows.Forms.Form
$main_form.Text ='google text-to-speech'
$main_form.Width = 500
$main_form.Height = 500
$main_form.AutoSize = $true



$TextBox = New-Object System.Windows.Forms.TextBox
$TextBox.Width = 450
$TextBox.AutoSize = $true
$TextBox.Location = New-Object System.Drawing.Point(50,200)
$TextBox.Text = Get-Clipboard -Format Text
$main_form.Controls.Add($TextBox)

$button = New-Object System.Windows.Forms.Button
$button.Text = 'OK'
$button.Location = New-Object System.Drawing.Point(400,250)
$button.add_Click({Click_Button});
$main_form.Controls.Add($button)





function Click_Button
{
$json.input.text = $TextBox.Text
$json | ConvertTo-Json | Set-Content $p\text.json
}

$main_form.ShowDialog()

Iska 17-12-2020 16:54 2943298

YuS_2, InputBox даёт возможность зараз подставить умолчальное значение из Буфера обмена. И не во всех ОС работает вставка в окно консоли без предварительных настроек.

9119, с предыдущей страницы: Создание настраиваемого поля ввода - PowerShell | Microsoft Docs.

9119 17-12-2020 17:11 2943302

Вложений: 1
Iska, я изучил эту информацию и не только ее...
все дело в том, что как не крути не получается у меня сделать в несколько строк это.
Пробовал через TextBox, ListBox. ComboBox.
Все время одна строка... (

upd: решил.
Код:

$TextBox.Multiline = $True;
Но, все же непонятно как добавить скрол, если вставленный текст весь не виден в окне (приходится опускаться/подыматься стрелками клавы)
Также в данном поле не работает почему-то сочетание ctrl+a, например.
Если владеете инфой - объясните на пальцах, пож.

YuS_2 17-12-2020 19:02 2943316

Цитата:

Цитата 9119
нужны были разные варианты, но предпочтительнее все таки окно отдельное.
Планирую в нем сделать листбоксы и для настройки других параметров в text.json. »

Ну, это уже другое дело. Раз уж нравится больше настраиваемая форма, то надо в условия задачи это и вписать...

Цитата:

Цитата Iska
InputBox даёт возможность зараз подставить умолчальное значение из Буфера обмена. »

Это, как раз, не проблема, один условный блок всё решает...

Цитата:

Цитата Iska
И не во всех ОС работает вставка в окно консоли без предварительных настроек. »

С этим уже хуже. Но и ТС, вроде уточнил, что форма подходит больше...

Iska 17-12-2020 19:47 2943319

Цитата:

Цитата 9119
Но, все же непонятно как добавить скрол, если вставленный текст весь не виден в окне (приходится опускаться/подыматься стрелками клавы) »

View Multiple Lines in TextBox Control - Windows Forms .NET Framework | Microsoft Docs

Цитата:

Цитата 9119
Также в данном поле не работает почему-то сочетание ctrl+a, например. »

Если задано свойство .Multiline — не работает. Вроде как старый, известный баг. Который то «лечится», то возвращается заново.

Косо-криво на верхнем уровне можно обойти своим обработчиком:
Скрытый текст
Код:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

[System.Windows.Forms.Application]::EnableVisualStyles()

$oForm                  = New-Object System.Windows.Forms.Form

$oForm.Text            = 'Sample form'
$oForm.Size            = New-Object System.Drawing.Size(300,200)
$oForm.StartPosition    = 'CenterScreen'

$oTextBox              = New-Object System.Windows.Forms.TextBox
$oTextBox.Location      = New-Object System.Drawing.Point(10,40)
$oTextBox.Size          = New-Object System.Drawing.Size(260,80)
$oTextBox.Multiline    = $true
$oTextBox.AcceptsReturn = $true
$oTextBox.WordWrap      = $false
$oTextBox.ScrollBars    = [System.Windows.Forms.ScrollBars]::Both

$oTextBox.Add_KeyDown({
  if ($_.Modifiers -eq [System.Windows.Forms.Keys]::Control -and $_.KeyCode -eq [System.Windows.Forms.Keys]::A) {
    $oTextBox.SelectAll()
  }
})

$oForm.Controls.Add($oTextBox)

$oForm.Add_Shown({$oTextBox.Select()})
$oForm.ShowDialog()



Цитата:

Цитата YuS_2
Это, как раз, не проблема, один условный блок всё решает... »

Поясните примером.

YuS_2 17-12-2020 21:38 2943328

Цитата:

Цитата Iska
Поясните примером. »

типа:
Код:

...
$json.input.text = if ($a = get-clipboard){$a}else{read-host "Пожалуйста, введите или вставьте из буфера текст"}
...


Iska 17-12-2020 22:55 2943334

YuS_2, спасибо, ясно. В этом случае мы не видим промежуточный текст.

9119 18-12-2020 02:45 2943351

Спасибо всем кто отозвался!
Впринципе результат удовлетворительный и тему можно помечать как решенную, но все же попрошу помощи в оптимизации "написанного").
А именно: (опишу процесс, чтобы было более понятно)

Все делается в PS (GUI для работы с google text-to-speech):
1) через окно пишем нужные параметры в text.json для последующего запроса на сервак.
2) Шлем запрос на сервак, ответ сервака пишем в source.txt
здесь таймаут (ждем пока пишется ответ с сервака)
3) Корректируем source.txt как надо и пишем результат в out.txt
здесь таймаут (ждем обработки п.3)
4) Еще корректируем нюансы и пишем полученное в out1.txt
здесь таймаут (ждем отработки п.4)
5) Перекодируем out1.txt в конечный файл mp3.

Нужно как-то убрать таймауты... А вот как- ума не приложу.
Поясню - тестил на небольших статьях на 2 минуты, поставил после п2 таймаут в 10 сек, работает корректно. Но если этот текст будет минут на 15-20, то уже 10сек таймаута будет мало..п.3 начнется раньше, чем будет записан source.txt.... и будет ошибка на выходе.
Надеюсь понятно объяснил...(

p.s. крутится идея как-то привзязаться к наличию и размеру txt файлов (например, если source.txt создан и размер его больше чем 0 байт - тогда переходим к следующему шагу, ну или как-то так).
Нужен универсальный вариант, без подбора таймаутов вручную, чтобы работало с любой длинной текста.


сам скрипт
echo off | Out-Null
$p='E:\11\bin'
$s='E:\11'
echo ""
echo ""
echo ("=================================================Google Text-To=Speech=================================================")
echo ""
timeout /t 2 | Out-Null
echo ("1) Скачиваем файл...")
echo ""
start $p/hidec.exe download.bat
timeout /t 10 | Out-Null


echo ("2) Выделяем код...")
echo ""
findstr /I "audioContent" $p\source.txt > $p\out.txt
del $p\source.txt
timeout /t 2 | Out-Null


echo ("3) Обработываем полученный код...")
echo ""
start $p/hidec.exe text_mod.bat
timeout /t 5 | Out-Null


echo ("4) Конвертируем в mp3...")
echo ""
echo ""
& $p\b64.exe -d out1.txt $s\audio\sound.mp3
del $p\out1.txt

echo ("=========================================================Готово!================================== ====================")
timeout /t 2 | Out-Null
explorer $s\audio
exit

Foreigner 18-12-2020 04:37 2943354

Цитата:

Цитата 9119
google text-to-speech »

А он лучше, чем штатный голосовой движок? Например переводим текст в wav:
Код:

using namespace System.Speech
using namespace System.Speech.Synthesis

param (
    [Parameter (Mandatory = $false, ValueFromPipeline = $true)]
    [string]
    $text = $(Get-Clipboard | Out-String),

<# Надо подключать дополнительные "голоса", через реестр, например Павла.

    [Parameter(Mandatory = $false)]
    [VoiceGender]
    $sex = 'female',

#>

    [Parameter(Mandatory = $false)]
    [string]
    $culture = 'ru-RU'
)

if ($PSEdition -eq 'Core')
    { Write-Warning 'Not Working on PowerShell 7'; return }


$speaker = [SpeechSynthesizer]::new()

if ($culture -eq 'en-US')
{
    $speaker.SelectVoice('Microsoft Zira Desktop')
    $speaker.Rate = -1
}

else
{
    $speaker.SelectVoice('Microsoft Irina Desktop')
    $speaker.Rate = 1
}

$speaker.SetOutputToWaveFile("$HOME\Desktop\out.wav")
$speaker.Speak($text)

Start-Sleep -Milliseconds 1500

$speaker.Dispose()


YuS_2 18-12-2020 07:51 2943359

Цитата:

Цитата Iska
В этом случае мы не видим промежуточный текст. »

Если очень надо, то можно выводить в консоль буфер:
Код:

...{$a;write-host $a} else {...

9119 18-12-2020 09:49 2943370

Цитата:

Цитата Foreigner
А он лучше, чем штатный голосовой движок »

да, значительно.
Просто сам додумать не могу как избавится от таймаутов...

Iska 18-12-2020 14:43 2943390

Цитата:

Цитата YuS_2
Если очень надо, то можно выводить в консоль буфер: »

[Произносится медленно, нараспев:] А поправить :)? В смысле — ежели надо не только вывести, но и оперативно поправить содержимое и зараз же продолжить?

YuS_2 18-12-2020 20:42 2943426

Цитата:

Цитата Iska
В смысле — ежели надо не только вывести, но и оперативно поправить содержимое и зараз же продолжить? »

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

9119 18-12-2020 21:15 2943429

Помогите офоормить правильно для PS:

помесь ps, cmd и ерунды)
Код:

$p='рабочая/папка'

:CHECK1
if (Test-Path -Path $p\source.txt=true) {      #Test-Path возвращает true, если файл существует

        write-host "Файл скачан!"
        goto :RUN1
else goto :CHECK1



:RUN1
%Команда1%
%Команда2%
%Команда3%



проверяем наличие в папке файла source.txt, и переходим к выполнению команд, если файла там нет - повторяем поиск...и циклим поиск пока файл там не появится.
В идеале чтобы проверяло не только наличие файла, но и его размер, чтобы он был >0

Iska 18-12-2020 22:00 2943431

Цитата:

Цитата YuS_2
Но меня опять терзают смутные сомнения , что первоначальная задача растет, как на дрожжах, »

Ага. Очередная «Каша из топора»™ :).

9119 18-12-2020 22:05 2943432

Цитата:

Цитата Iska
Очередная «Каша из топора» »

upd. Вопрос решен.
Реализовал через проверку размера файла и цикла while.

Код:

Write-Host "1) Загрузка файла..."
timeout /t 2 | Out-Null
while($true) {
$check1 = Get-ChildItem $p\source.txt | % {[int]($_.length / 1kb)}
IF ($check1 -gt 1){
timeout /t 2 | Out-Null
Write-Host "Файл загружен"
break
}}



Спасибо всем за помощь и наводки!


Время: 16:06.

Время: 16:06.
© OSzone.net 2001-