Polecenie (a) wsadowe systemu Windows do odczytu pierwszej linii z pliku tekstowego


84

Jak odczytać pierwszą linię z pliku tekstowego przy użyciu pliku wsadowego systemu Windows? Ponieważ plik jest duży, chcę zająć się tylko pierwszą linią.


1
Wypróbuj narzędzie GNU32 "head". Nie myśl, że to, czego szukasz, zostanie łatwo osiągnięte za pomocą samego DOS Batch.
Nasir

@Nasir, czy nie można tego zrobić za pomocą wbudowanego polecenia?
Prajwal Dhatwalia

Odpowiedzi:


48

Oto plik wsadowy ogólnego przeznaczenia do wydrukowania pierwszych nwierszy z pliku takiego jak headnarzędzie GNU , zamiast tylko jednego wiersza.

@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

Na przykład:

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

Obecnie nie liczy pustych wierszy. Podlega również ograniczeniu długości wiersza pliku wsadowego do 8 KB.


11
FYI: "GOTO: EOF" To specjalna etykieta, która wyjdzie ze skryptu bez konieczności definiowania specjalnej etykiety ": exit". Jest to również przydatne podczas definiowania podprogramów w pakiecie (co to powiesz? Podprogramy? Tak)
Steven

4
Wydaje się, że bombarduje to moje pliki tekstowe o rozmiarze kilku GB ... W jednym pliku dało mi to błąd „Brak pamięci” przy próbie zwrócenia 10 wierszy, w drugim pliku zwróciło tylko jedną pustą linię, gdy poprosił o zwrot 10 linii. Jakieś pomysły, dlaczego tak się dzieje?
Dan,

1
@Dan - Jak długie są linie? FOR / F „ignoruje” wiersze dłuższe niż 8191 bajtów. Ale zastanawiam się, czy błąd „Brak pamięci” pojawia się, jeśli napotka naprawdę długą linię.
dbenham

@StephanMuller - Zobacz mój komentarz do Dana powyżej
dbenham

Jak napisano, ta odpowiedź zignoruje puste wiersze. Zignoruje również wiersze zaczynające się od średnika ;, domyślnego znaku FOR / F EOL. Jeśli poprosisz o 10 wierszy, wydrukuje pierwsze 10 wierszy, które nie są puste i nie zaczynają się od ;.
dbenham

224

uh? imo to jest znacznie prostsze

  set /p texte=< file.txt  
  echo %texte%

16
+1, To jest najlepsze, gdy działa :-) Ma następujące ograniczenia 1) Maksymalna długość linii 1021 bajtów, bez EOL. 2) Plik musi korzystać z EOL w stylu Windows CarriageReturn LineFeed. 3) Końcowe znaki sterujące zostaną usunięte z wiersza
dbenham

4
Ponadto tekst powinien być jawnie niezdefiniowany przed odczytaniem pliku, na wypadek gdyby pierwsza linia była pusta.
dbenham

Oto kilka dodatkowych wskazówek dotyczących przycinania sznurka. echo %texte:~3%na przykład pominie pierwsze trzy znaki. Jest to przydatne, gdy czytasz plik UTF-8 z BOM.
KargWare

22

Uh wy ...

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
Jeśli plik ma więcej niż 11 wierszy, wydrukuje więcej niż pierwszy, na przykład: 1 :, 11 :, 21 :, itd ...
Cesar Romero

1
Dobry chwyt, Cesar! Zawsze staram się unikać cytatów, ponieważ mnie denerwują, ale w tym przypadku był to zły pomysł. Aby naprawić, zmień findstr "^1:"i zyskaj ciepło i ochronę podwójnych cudzysłowów. Lub, jeśli gardzisz cytatami takimi jak ja i chcesz żyć niebezpiecznie, użyjfindstr /b 1:
Amit Naidu

4
jeśli chcesz go bez cudzysłowów i bez opcji / b, a następnie po prostu uciec od daszka: findstr ^^1.
dbenham

Świetna wskazówka dbenham, ucieczka w cmd zawsze mi umyka. Nawiasem mówiąc, nie używaj tej metody do dużych plików, w rzeczywistości odczytuje ona cały plik i jest bardzo nieefektywna. Moje jedyne kryteria dla tego rozwiązania to A) Powinien to być pojedynczy wiersz B) Powinien być łatwy do zapamiętania lub odtworzenia z pamięci i typu, a nie kopiuj-wklej C) Brak zewnętrznych narzędzi. set /pRozwiązanie jest o wiele bardziej efektywne w przypadku dużych plików.
Amit Naidu

2
Ponadto dołącza numer wiersza do wiersza tekstu, który faktycznie chcesz! Dlatego nie jest tak przydatny, gdy potrzebujesz tylko tekstu.
Ross Presser,

11

Możesz spróbować:

@echo off

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

edytuj Lub załóżmy, że masz cztery kolumny danych i chcesz od piątego wiersza do dołu, spróbuj tego:

@echo off

for /f "skip=4 tokens=1-4" %%a in (junkl.txt) do (
  echo %%a %%b %%c %%d
)

1
To dało mi wskazówkę, której potrzebowałem, ale nie była całkiem dobra. Nie jestem pewien, jaka była właściwa procedura, ale włączyłem to rozwiązanie do ostatecznego rozwiązania. patrz stackoverflow.com/questions/130116#130209
Jesse Vogt

2
Problem z tym rozwiązaniem polega na tym, że ogranicza on spację zamiast znaku nowej linii i nie można mieć nazwy pliku ze spacjami. Możesz rozwiązać te problemy za pomocą opcji delims i usebackq w pętli for.
indyw

Pracowało dla mnie, ale musiałem dodać, "delims="aby wydrukować pełne nazwy folderów wraz ze spacjami.
GChuf


4

Nieco opierając się na odpowiedziach innych osób. Teraz możesz określić plik, z którego chcesz odczytać i zmienną, w której chcesz umieścić wynik:

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

Oznacza to, że możesz użyć powyższego w ten sposób (zakładając, że nazwałeś to getline.bat)

c:\> dir > test-file
c:\> getline variable test-file
c:\> set variable  
variable= Volume in drive C has no label.

3

Jedna linijka, przydatna do przekierowania stdout z „>”:

@for /f %%i in ('type yourfile.txt') do @echo %%i & exit

2

Spróbuj tego

@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

1

Problem z EXIT /Brozwiązaniami, gdy bardziej realistycznie jest w pliku wsadowym, jako tylko jedna jego część, jest następujący. We wspomnianym pliku wsadowym nie ma żadnego dalszego przetwarzania po rozszerzeniu EXIT /B. Zwykle partie to znacznie więcej niż jedno, ograniczone zadanie.

Aby przeciwdziałać temu problemowi:

@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

(Jednak tak zwane trujące postacie nadal będą stanowić problem.)

Więcej na temat uzyskiwania określonej linii za pomocą poleceń wsadowych:

Jak uzyskać n-ty, pierwszy i ostatni wiersz pliku tekstowego? ” Http://www.netikka.net/tsneti/info/tscmd023.htm

[Dodano 28 sierpnia 2012 r.] Można też mieć:

@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 jest prawdopodobnie najdelikatniejszym rozwiązaniem, jakie zostało zaprezentowane. W tym wątku @Spaceballs. Generalnie napisałbym set / p "texte" = <"file.txt", ale to nie ma znaczenia. Zauważ, że nawet to rozwiązanie jest podatne na problemy ze znakami trującymi, tzn. Może zawieść w zależności od tego, co zawiera plik.txt.
Timo Salmi

1

Aby cicle plik ( file1.txt, file1[1].txt, file1[2].txt, itd.):

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%

I to działa.


Wyjaśnienie jest następujące: set /ppyta poprzez monit; jednakże w przypadku przekierowania pliku <natychmiast pobiera zawartość pliku po zachęcie; a ponieważ pierwsza linia kończy się końcem linii, w tym miejscu zachęta przestaje czytać, a tym samym przechowuje tylko pierwszą linię w zmiennej.
sdbbs

0

Zauważ, że podejście do pliku wsadowego będzie ograniczone do limitu linii dla procesora poleceń DOS - zobacz Jaki jest limit długości wiersza poleceń? .

Więc jeśli spróbujesz przetworzyć plik, który ma jakiekolwiek linie zawierające więcej niż 8192 znaków, skrypt po prostu je pominie, ponieważ wartość nie może być zatrzymana.


0

Inny sposób

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
Polecam używanie pliku .bat TYLKO w ostateczności. Jeśli to wszystko możliwe, zawsze staraj się używać "prawdziwego" języka skryptowego: Powershell, WSH, Python ... WSZYSTKO oprócz plików .bat.
paulsm4

2
Partia nie jest taka zła (jeśli wiesz, co robisz; tak samo jak w każdym innym języku). hhay: twój kod nie działa.
Stephan

ponieważ nie używasz opóźnionego rozwijania
Stephan,

1
@ paulsm4: Co jest nie tak z plikami wsadowymi? Działa na wszystkich wersjach systemu Windows i ma unikalną funkcję zwaną opóźnionym rozszerzaniem, dzięki której magia może działać bez instalowania oprogramowania innych firm, o ile ją rozumiesz. Czy wiesz, że możesz korzystać z protokołu TCP / IP z DOS i plikami wsadowymi na długo przed Powershell i dotNet?
Zimba

0

Oto obejście za pomocą powershell:

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

(Możesz łatwo przeczytać również zakres wierszy za pomocą powershell (Get-Content file.txt)[0..3])

Jeśli chcesz ustawić zmienną w skrypcie wsadowym, jako pierwszą linię file.txtmożesz użyć:

for /f "usebackq delims=" %%a in (`powershell ^(Get-Content file.txt^)[0]`) do (set "head=%%a")

Powershell jest bardzo wolny
Anic17

-1

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

Drukuje pierwszą linię, a następnie czeka, aż użytkownik naciśnie klawisz, aby wydrukować następną linię. Po wydrukowaniu wymaganych linii naciśnij Ctrl + C, aby zatrzymać.

@ Ross Presser: Ta metoda drukuje tylko wiersze, a nie numery wierszy dodawane na początku.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.