Пакетные команды Windows для чтения первой строки из текстового файла

85

Как я могу прочитать первую строку из текстового файла с помощью командного файла Windows? Поскольку файл большой, я хочу иметь дело только с первой строкой.

Джесси Фогт
источник
1
Попробуйте утилиту "голова" GNU32. Не думайте, что то, что вам нужно, будет легко достигнуто с помощью только DOS Batch.
Насир,
@Nasir, а встроенной командой нельзя?
Prajwal Dhatwalia,

Ответы:

48

Вот командный файл общего назначения для печати верхних nстрок из файла, такого как headутилита GNU , вместо одной строки.

@echo off

if [%1] == [] goto usage
if [%2] == [] goto usage

call :print_head %1 %2
goto :eof

REM
REM print_head
REM Prints the first non-blank %1 lines in the file %2.
REM
:print_head
setlocal EnableDelayedExpansion
set /a counter=0

for /f ^"usebackq^ eol^=^

^ delims^=^" %%a in (%2) do (
        if "!counter!"=="%1" goto :eof
        echo %%a
        set /a counter+=1
)

goto :eof

:usage
echo Usage: head.bat COUNT FILENAME

Например:

Z:\>head 1 "test file.c"
; this is line 1

Z:\>head 3 "test file.c"
; this is line 1
    this is line 2
line 3 right here

В настоящее время он не считает пустые строки. На него также распространяется ограничение на длину строки командного файла, равное 8 КБ.

индив
источник
11
К вашему сведению: «GOTO: EOF» Это специальная метка, которая выйдет из скрипта без необходимости определять специальную метку «: exit». Это также полезно при определении подпрограмм в пакете (что вы говорите? Подпрограммы? Ага)
Стивен
4
Кажется, это разбомбилось в моих нескольких текстовых файлах ГБ ... В одном файле он дал мне ошибку «Недостаточно памяти» при попытке вернуть 10 строк, в другом файле он просто вернул одну пустую строку, когда попросил его вернуть 10 строк. Есть идеи, почему это происходит?
Дэн
1
@Dan - Какова длина очередей? FOR / F «игнорирует» строки длиннее 8191 байта. Но мне интересно, возникает ли ошибка «Мало памяти», если встречается действительно длинная строка.
dbenham
@StephanMuller - См. Мой комментарий Дэну выше
dbenham
Как написано, этот ответ будет игнорировать пустые строки. Он также будет игнорировать строки, начинающиеся с точки с запятой ;, символа FOR / F EOL по умолчанию. Если запросить 10 строк, он напечатает первые 10 строк, которые не пусты и не начинаются ;.
dbenham
225

а? имо это намного проще

  set /p texte=< file.txt  
  echo %texte%
Космические шары
источник
16
+1, Это лучший вариант, когда он работает :-) Имеет следующие ограничения: 1) Максимальная длина строки 1021 байт, не считая EOL. 2) Файл должен использовать EOL в стиле Windows для CarriageReturn LineFeed. 3) Конечные управляющие символы будут удалены из строки
dbenham
5
Кроме того, текст должен быть явно неопределенным перед чтением файла на случай, если первая строка пуста.
dbenham
Вот несколько дополнительных советов по обрезке струны. echo %texte:~3%например, пропустит первые три символа. Это полезно, когда вы читаете файл UTF-8 с спецификацией.
KargWare 03 июн.2020,
22

Эээ, ребята ...

C:\>findstr /n . c:\boot.ini | findstr ^1:

1:[boot loader]

C:\>findstr /n . c:\boot.ini | findstr ^3:

3:default=multi(0)disk(0)rdisk(0)partition(1)\WINNT

C:\>
Амит Найду
источник
2
Если в файле более 11 строк, он напечатает больше, чем первая, например: 1 :, 11 :, 21: и т. Д.
Сезар Ромеро
1
Хороший улов, Цезарь! Я всегда стараюсь избегать цитат, потому что они меня раздражают, но в данном случае это была плохая идея. Чтобы исправить это, изменитесь на findstr "^1:"и получите теплоту и защиту двойных кавычек. Или, если вы презираете такие цитаты, как я, и хотите жить опасно, используйтеfindstr /b 1:
Амит Найду
4
если вы хотите без кавычек и без опции / б , то просто избежать каретки: findstr ^^1.
dbenham
Отличный намек, dbenham, побег в cmd всегда ускользает от меня. Кстати, пожалуйста, не используйте этот метод для больших файлов, он фактически читает весь файл и очень неэффективен. Моими единственными критериями для этого решения были A) Это должна быть одна строка B) Его должно быть легко запомнить или воссоздать из памяти и набрать, а не копировать и вставить C) Никаких внешних инструментов. set /pРешение является гораздо более эффективным для больших файлов.
Амит Найду
2
Кроме того, он добавляет номер строки к строке текста, которую вы действительно хотите! Поэтому не очень полезно, когда вам просто нужен текст.
Росс Прессер,
11

Вы можете попробовать:

@echo off

for /f %%a in (sample.txt) do (
  echo %%a
  exit /b
)

edit Или, скажем, у вас есть четыре столбца данных и вы хотите от 5-й строки до конца, попробуйте следующее:

@echo off

for /f "skip=4 tokens=1-4" %%a in (junkl.txt) do (
  echo %%a %%b %%c %%d
)
Росс Фурман
источник
1
Это дало мне ключ к разгадке, но он был не совсем верным. Не уверен, что это за процедура, но я включил это решение в окончательное решение. см. stackoverflow.com/questions/130116#130209
Джесси Фогт,
2
Проблема этого решения в том, что оно ограничивает пробелы вместо новой строки, и вы не можете иметь имя файла с пробелами. Вы можете исправить эти проблемы с помощью параметров delims и usebackq в цикле for.
indiv
Сработало для меня, но мне пришлось добавить, "delims="чтобы распечатать полные имена папок вместе с пробелами.
GChuf
4

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

@echo off
for /f "delims=" %%x in (%2) do (
set %1=%%x
exit /b
)

Это означает, что вы можете использовать приведенное выше (при условии, что вы назвали его getline.bat)

c:\> dir > test-file
c:\> getline variable test-file
c:\> set variable  
variable= Volume in drive C has no label.
Рэй Хейс
источник
3

Один лайнер, полезный для перенаправления стандартного вывода с помощью ">":

@for /f %%i in ('type yourfile.txt') do @echo %%i & exit
PabloG
источник
2

Попробуй это

@echo off
setlocal enableextensions enabledelayedexpansion
set firstLine=1
for /f "delims=" %%i in (yourfilename.txt) do (
    if !firstLine!==1 echo %%i
    set firstLine=0
)
endlocal
Сарат К.С.
источник
2

Чтобы Cicle файл ( file1.txt, file1[1].txt, file1[2].txtи т.д.):

START/WAIT C:\LAERCIO\DELPHI\CICLADOR\dprCiclador.exe C:\LAERCIUM\Ciclavel.txt

rem set/p ciclo=< C:\LAERCIUM\Ciclavel.txt:
set/p ciclo=< C:\LAERCIUM\Ciclavel.txt

rem echo %ciclo%:
echo %ciclo%

И это работает.

Лаэрчио
источник
Объяснение этому: set /pспрашивает через подсказку; однако при перенаправлении файла <он сразу же получает содержимое файла по запросу; и поскольку первая строка заканчивается строкой, в этот момент подсказка перестает читать и, таким образом, сохраняет только первую строку в переменной.
sdbbs
1

Проблема с EXIT /Bрешениями, когда более реалистично внутри командного файла, поскольку только одна его часть, заключается в следующем. В указанном командном файле нет последующей обработки послеEXIT /B . Обычно партии - это гораздо больше, чем просто одна ограниченная задача.

Чтобы противостоять этой проблеме:

@echo off & setlocal enableextensions enabledelayedexpansion
set myfile_=C:\_D\TEST\My test file.txt
set FirstLine=
for /f "delims=" %%i in ('type "%myfile_%"') do (
  if not defined FirstLine set FirstLine=%%i)
echo FirstLine=%FirstLine%
endlocal & goto :EOF

(Однако так называемые ядовитые символы по-прежнему будут проблемой.)

Подробнее о получении конкретной строки с помощью пакетных команд:

Как получить n-ю, первую и последнюю строку текстового файла? " Http://www.netikka.net/tsneti/info/tscmd023.htm

[Добавлено 28 августа 2012 г.] Также можно иметь:

@echo off & setlocal enableextensions
set myfile_=C:\_D\TEST\My test file.txt
for /f "tokens=* delims=" %%a in (
  'type "%myfile_%"') do (
    set FirstLine=%%a& goto _ExitForLoop)
:_ExitForLoop
echo FirstLine=%FirstLine%
endlocal & goto :EOF
Тимо Салми
источник
Set / p texte = <file.txt, вероятно, является лучшим решением, которое было представлено. В этой теме автор @Spaceballs. В общем, я бы написал set / p "texte" = <"file.txt", но это не относится к делу. Обратите внимание, что даже это решение подвержено проблемам с ядовитыми символами, то есть может дать сбой в зависимости от того, что содержит файл .txt.
Timo Salmi
0

Обратите внимание, подходы к пакетным файлам будут ограничены лимитом строки для командного процессора DOS - см. Какое ограничение на длину командной строки? .

Поэтому, если вы пытаетесь обработать файл, в котором есть строки, превышающие 8192 символа, сценарий просто пропустит их, поскольку значение не может быть сохранено.

Kevinjansz
источник
0

По-другому

setlocal enabledelayedexpansion
@echo off
for /f "delims=" %%i in (filename.txt) do (
if 1==1 (
set first_line=%%i
echo !first_line!
goto :eof
))
привет
источник
2
Я бы рекомендовал использовать файл .bat ТОЛЬКО в крайнем случае. Если все это возможно, всегда старайтесь использовать "настоящий" язык сценариев: Powershell, WSH, Python ... НИЧЕГО, кроме файлов .bat.
paulsm4
2
Batch не что плохо (если вы знаете, что вы делаете, так же , как с любым другим языком). хай: твой код не работает.
Стефан
потому что вы не используете отложенное расширение
Стефан
1
@ paulsm4: Что не так с пакетными файлами? Он работает на всех разновидностях Windows и имеет уникальную функцию, называемую delayedexpansion, которая позволяет волшебству происходить без установки стороннего программного обеспечения, если вы это понимаете. Знаете ли вы, что вы можете использовать TCP / IP с DOS и пакетными файлами задолго до Powershell и dotNet?
Зимба
0

Вот обходной путь powershell:

powershell (Get-Content file.txt)[0]

(Вы также можете легко прочитать ряд строк с powershell (Get-Content file.txt)[0..3] )

Если вам нужно установить переменную внутри пакетного сценария, в качестве первой строки file.txtвы можете использовать:

for /f "usebackq delims=" %%a in (`powershell ^(Get-Content file.txt^)[0]`) do (set "head=%%a")
ммдж
источник
Powershell очень медленный
Anic17 02
-1

for /f "delims=" %a in (downing.txt) do echo %a & pause>nul

Печатает 1-ю строку, затем ожидает, пока пользователь нажмет клавишу для печати следующей строки. После печати необходимых строк нажмите Ctrl + C для остановки.

@Ross Presser: этот метод печатает только строки, но не добавляет номера строк.

Зимба
источник