Удалить конечные пробелы из файла с помощью пакета Windows? - PullRequest
3 голосов
/ 16 февраля 2012

Как можно обрезать все конечные пробелы из текстового файла с помощью командной строки Windows?

Ответы [ 7 ]

8 голосов
/ 17 февраля 2012

Функция DosTips RTRIM, которую цитирует Бен Хокинг, может использоваться для создания сценария, который может корректно обрезать каждую строку в текстовом файле.Тем не менее, функция является относительно медленной.

Пользователь DosTips (и модератор) aGerman разработали очень эффективный алгоритм правой подстройки .Он реализовал алгоритм в виде пакетного «макроса» - интересной концепции хранения сложных мини-скриптов в переменных среды, которые могут быть выполнены из памяти.Макросы с аргументами сами по себе являются главной темой обсуждения, которая не имеет отношения к этому вопросу.

Я извлек алгоритм Алгермана и поместил его в следующий пакетный скрипт.Сценарий ожидает имя текстового файла в качестве единственного параметра и пересекает пробелы справа от каждой строки в файле.

@echo off
setlocal enableDelayedExpansion
set "spcs= "
for /l %%n in (1 1 12) do set "spcs=!spcs!!spcs!"
findstr /n "^" "%~1" >"%~1.tmp"
setlocal disableDelayedExpansion
(
  for /f "usebackq delims=" %%L in ("%~1.tmp") do (
    set "ln=%%L"
    setlocal enableDelayedExpansion
    set "ln=!ln:*:=!"
    set /a "n=4096"
    for /l %%i in (1 1 13) do (
      if defined ln for %%n in (!n!) do (
        if "!ln:~-%%n!"=="!spcs:~-%%n!" set "ln=!ln:~0,-%%n!"
        set /a "n/=2"
      )
    )
    echo(!ln!
    endlocal
  )
) >"%~1"
del "%~1.tmp" 2>nul

Если сценарий называется rtrimFile.bat, его можно вызватьиз командной строки:

rtrimFile "fileName.txt"

Замечание о производительности Оригинальная функция DosTips rtrim выполняет линейный поиск и по умолчанию обрезает до 32 пробелов.Он должен выполнять итерацию один раз за пробел.

Алгоритм aGerman использует бинарный поиск и способен обрезать максимальный размер строки, допустимый для пакета (до ~ 8k пробелов), за 13 итераций.

К сожалению, пакет очень медленный, когда дело доходит до обработки текста.Даже с эффективной функцией rtrim, мне нужно ~ 70 секунд, чтобы обрезать файл размером 1 МБ на моей машине.Проблема в том, что простое чтение и запись файла без каких-либо изменений занимает значительное время.Этот ответ использует цикл FOR для чтения файла, в сочетании с FINDSTR, чтобы префикс каждой строки с номером строки, чтобы сохранить пустые строки.Это переключает отложенное расширение, чтобы предотвратить повреждение !, и использует операцию поиска и замены, чтобы удалить префикс номера строки из каждой строки.Все это еще до того, как он начнет работать.

Производительность можно почти удвоить, если использовать механизм чтения альтернативных файлов , использующий set /p.Однако метод set / p ограничен ~ 1 Кбайт на строку, и он удаляет конечные управляющие символы из каждой строки.

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

Если вы не можете использовать не родное программное обеспечение, тогда вы можете попробовать VBScript или JScript с помощьюпакетная команда CSCRIPT.Любой из них был бы НАМНОГО быстрее.

ОБНОВЛЕНИЕ - Быстрое решение с JREPL.BAT

JREPL.BAT - это утилита поиска / замены регулярного выраженияэто может очень эффективно решить проблему.Это чистый скрипт (гибридный пакет / JScript), который работает на любом компьютере с Windows начиная с XP.Не требуются сторонние exe-файлы.

С JREPL.BAT где-нибудь в вашей переменной PATH вы можете убрать конечные пробелы из файла "test.txt" с помощью этой простой команды:

jrepl " +$" "" /f test.txt /o -

ЕслиВы помещаете команду в пакетный скрипт, затем перед командой необходимо указать CALL:

call jrepl " +$" "" /f test.txt /o -
4 голосов
/ 16 февраля 2012

Получите себе копию CygWin или sed пакета из GnuWin32 .

Затем используйте ее с командой:

sed "s/ *$//" inputFile >outputFile
2 голосов
/ 16 февраля 2012

Dos Tips имеет реализацию RTrim , которая работает для пакетных файлов:

:rTrim string char max -- strips white spaces (or other characters) from the end of a string
::                     -- string [in,out] - string variable to be trimmed
::                     -- char   [in,opt] - character to be trimmed, default is space
::                     -- max    [in,opt] - maximum number of characters to be trimmed from the end, default is 32
:$created 20060101 :$changed 20080219 :$categories StringManipulation
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
call set string=%%%~1%%
set char=%~2
set max=%~3
if "%char%"=="" set char= &rem one space
if "%max%"=="" set max=32
for /l %%a in (1,1,%max%) do if "!string:~-1!"=="%char%" set string=!string:~0,-1!
( ENDLOCAL & REM RETURN VALUES
    IF "%~1" NEQ "" SET %~1=%string%
)
EXIT /b

Если вы не привыкли использовать функции в пакетных файлах, прочтите это .

1 голос
/ 23 июня 2017

Есть хороший трюк для удаления завершающих пробелов, основанный на этом ответе пользователя Aacini ; Я изменил его так, чтобы все остальные пробелы в строке были сохранены. Итак, вот код:

@echo off
setlocal EnableDelayedExpansion

rem // This is the input string:
set "x=  This is   a text  string     containing  many   spaces.   "

rem // Ensure there is at least one trailing space; then initialise auxiliary variables:
set "y=%x% " & set "wd=" & set "sp="

rem // Now here is the algorithm:
set "y=%y: =" & (if defined wd (set "y=!y!!sp!!wd!" & set "sp= ") else (set "sp=!sp! ")) & set "wd=%"

rem // Return messages:
echo  input: "%x%"
echo output: "%y%"

endlocal

Однако этот подход не срабатывает, когда в строке встречается символ набора ^, !, ".

0 голосов
/ 26 июля 2016

Я только что нашел очень хорошее решение для обрезки пробелов строки:
Вы когда-нибудь вызывали подпрограмму, используя call, и расширяли все аргументы, используя %*? Вы заметите, что все начальные и / или конечные пробелы удалены. Любые пробелы, встречающиеся между другими символами, сохраняются; как и все остальные разделители токенов команд ,, ;, =, а также пробел без пробелов (код символа 0xFF). Этот эффект я собираюсь использовать для моего сценария:

@echo off

set "STR="
set /P STR="Enter string: "

rem /* Enable Delayed Expansion to avoid trouble with
rem    special characters: `&`, `<`, `>`, `|`, `^` */
setlocal EnableDelayedExpansion
echo You entered: `!STR!`
call :TRIM !STR!
echo And trimmed: `!RES!`
endlocal

exit /B

:TRIM
set "RES=%*"
exit /B

Этот скрипт ожидает введенную пользователем строку, которая затем обрезается. Это, конечно, также может быть применено к строкам файла (о чем идет речь в первоначальном вопросе, но чтение такой строки построчно с помощью for /F в любом случае показано в других ответах, поэтому я пропущу это здесь). Чтобы обрезать строку только с одной стороны, добавьте один символ к противоположной стороне перед обрезкой и удалите ее впоследствии.

Этот подход имеет некоторые ограничения: он не обрабатывает символы %, !, ^ и " должным образом. Чтобы преодолеть это, необходимо выполнить несколько операций с промежуточными строками:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "STR="
set /P STR="Enter string: "

setlocal EnableDelayedExpansion
echo You entered: `!STR!`
set "STR=!STR:%%=%%%%!"
set "STR=!STR:"=""!^"
if not "%STR%"=="%STR:!=%" set "STR=!STR:^=^^^^!"
set "STR=%STR:!=^^^!%"
call :TRIM !STR!
set "RES=!RES:""="!^"
echo And trimmed: `!RES!`
endlocal

endlocal
exit /B

:TRIM
set "RES=%*"
exit /B

Обновление: Я только что понял, что символы &, <, > и | по-прежнему вызывают проблемы. Как только я найду решение, я вернусь сюда и исправлю код соответствующим образом ...

0 голосов
/ 05 ноября 2014

Я использую этот скрипт Python 2 для печати строк с конечными пробелами и удаления их вручную:

#!/usr/bin/env python2
import sys

if not sys.argv[1:]:
  sys.exit('usage: whitespace.py <filename>')

for no, line in enumerate(open(sys.argv[1], 'rb').read().splitlines()):
  if line.endswith(' '):
    print no+1, line

Я знаю, что Python не предустановлен для Windows, но, по крайней мере, он работает кроссплатформенно.

0 голосов
/ 17 февраля 2014

Хороший инструмент для удаления конечных пробелов в файлах в Windows: http://mountwhite.net/en/spaces.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...