คำสั่งแบตช์ของ Windows เพื่ออ่านบรรทัดแรกจากไฟล์ข้อความ


85

ฉันจะอ่านบรรทัดแรกจากไฟล์ข้อความโดยใช้ไฟล์แบตช์ของ Windows ได้อย่างไร เนื่องจากไฟล์มีขนาดใหญ่ฉันจึงต้องการจัดการกับบรรทัดแรกเท่านั้น


1
ลองใช้ยูทิลิตี้ GNU32 "head" อย่าคิดว่าสิ่งที่คุณเป็นหลังจากนั้นจะสำเร็จได้อย่างง่ายดายเพียงแค่ DOS Batch
Nasir

@ นาเซอร์ไม่สามารถทำได้ด้วยคำสั่ง inbuilt?
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 KB


11
FYI: "GOTO: EOF" นั่นคือป้ายกำกับพิเศษที่จะออกจากสคริปต์โดยไม่ต้องกำหนดป้ายกำกับ ": exit" แบบพิเศษ นอกจากนี้ยังมีประโยชน์เมื่อกำหนดรูทีนย่อยในแบตช์ (คุณพูดว่าอะไรรูทีนย่อยใช่)
สตีเวน

4
ดูเหมือนว่าจะระเบิดในไฟล์ข้อความหลาย GB ของฉัน ... ในไฟล์เดียวมันทำให้ฉันเกิดข้อผิดพลาด "หน่วยความจำไม่เพียงพอ" เมื่อพยายามส่งคืน 10 บรรทัดในอีกไฟล์หนึ่งมันจะส่งคืนบรรทัดว่างเพียงบรรทัดเดียวเมื่อขอให้ส่งคืน 10 บรรทัด มีความคิดว่าทำไมสิ่งนี้จึงเกิดขึ้น?
แดน

1
@ แดน - สายป่านยาวแค่ไหน? FOR / F "ละเว้น" บรรทัดที่ยาวกว่า 8191 ไบต์ แต่ฉันสงสัยว่าข้อผิดพลาด "หน่วยความจำไม่เพียงพอ" เกิดขึ้นหากพบว่ามีเส้นยาวมาก
dbenham

@StephanMuller - ดูความคิดเห็นของฉันถึง Dan ด้านบน
dbenham

ตามที่เขียนไว้คำตอบนี้จะไม่สนใจบรรทัดว่าง นอกจากนี้ยังจะไม่สนใจบรรทัดที่ขึ้นต้นด้วยอัฒภาค;ซึ่งเป็นอักขระเริ่มต้นของ FOR / F EOL ถ้าขอ 10 คู่สายแล้วมันจะพิมพ์ 10 ;บรรทัดแรกที่ไม่ว่างและไม่ได้เริ่มต้นด้วย
dbenham

226

เอ่อ? imo นี้ง่ายกว่ามาก

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

16
+1 นี่คือสิ่งที่ดีที่สุดเมื่อใช้งานได้ :-) มีขีด จำกัด ต่อไปนี้ 1) ความยาวบรรทัดสูงสุด 1,021 ไบต์ไม่รวม EOL 2) ไฟล์ต้องใช้ EOL สไตล์ Windows ของ CarriageReturn LineFeed 3) อักขระควบคุมต่อท้ายจะถูกตัดออกจากบรรทัด
dbenham

5
นอกจากนี้ควรไม่กำหนด texte อย่างชัดเจนก่อนที่จะอ่านไฟล์ในกรณีที่บรรทัดที่ 1 ว่างเปล่า
dbenham

นี่คือบางส่วนเคล็ดลับพิเศษสำหรับการตัดแต่งสตริง echo %texte:~3%ตัวอย่างเช่นจะข้ามสามตัวอักษรแรก นั่นเป็นประโยชน์เมื่อคุณกำลังอ่านไฟล์ UTF-8 ด้วย BOM
KargWare

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 :, ฯลฯ ...
Cesar Romero

1
จับ Cesar ได้ดี! ฉันพยายามหลีกเลี่ยงคำพูดเสมอเพราะมันทำให้ฉันรำคาญ แต่ในกรณีนี้มันเป็นความคิดที่ไม่ดี ในการแก้ไขให้เปลี่ยนfindstr "^1:"และรับความอบอุ่นและการปกป้องของเครื่องหมายคำพูดคู่ หรือถ้าคุณดูถูกคำพูดเช่นฉันและต้องการมีชีวิตอยู่อย่างอันตรายให้ใช้findstr /b 1:
Amit Naidu

4
ถ้าคุณต้องการได้โดยไม่ต้องคำพูดและไม่มีตัวเลือก b / findstr ^^1แล้วก็หลบหนีลูกศร:
dbenham

คำใบ้ที่ยอดเยี่ยม dbenham การหลบหนีใน cmd มักจะหนีฉันไป อย่างไรก็ตามโปรดอย่าใช้วิธีนี้กับไฟล์ขนาดใหญ่เนื่องจากจะอ่านไฟล์ทั้งหมดและไม่มีประสิทธิภาพมาก เกณฑ์เดียวของฉันสำหรับโซลูชันนี้คือ A) ควรเป็นบรรทัดเดียว B) ควรจดจำหรือสร้างใหม่จากหน่วยความจำและประเภทไม่ใช่คัดลอกวาง C) ไม่มีเครื่องมือภายนอก set /pวิธีการแก้ปัญหาที่อยู่ไกลมีประสิทธิภาพมากขึ้นสำหรับไฟล์ขนาดใหญ่
Amit Naidu

2
นอกจากนี้ยังนำหมายเลขบรรทัดไปไว้ข้างหน้าบรรทัดข้อความที่คุณต้องการจริงๆ! ดังนั้นจึงไม่มีประโยชน์เมื่อคุณต้องการเพียงแค่ข้อความ
Ross Presser

11

คุณอาจลองสิ่งนี้:

@echo off

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

แก้ไข หรือสมมติว่าคุณมีข้อมูลสี่คอลัมน์และต้องการจากแถวที่ 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
Jesse Vogt

2
ปัญหาของโซลูชันนี้คือการแบ่งช่องว่างแทนการขึ้นบรรทัดใหม่และคุณไม่สามารถมีชื่อไฟล์ที่มีช่องว่างได้ คุณสามารถแก้ไขปัญหาเหล่านี้ด้วยตัวคั่นและตัวเลือก usebackq ใน for loop
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

ซับเดียวมีประโยชน์สำหรับการเปลี่ยนเส้นทาง stdout ด้วย ">":

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

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'th บรรทัดแรกและบรรทัดสุดท้ายของไฟล์ข้อความได้อย่างไร " http://www.netikka.net/tsneti/info/tscmd023.htm

[เพิ่ม 28 ส.ค. 2555]นอกจากนี้ยังมี:

@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" แต่จะอยู่ข้างจุด โปรดทราบว่าแม้วิธีการแก้ปัญหานี้มีแนวโน้มที่จะเกิดปัญหาตัวละครที่เป็นพิษกล่าวคืออาจล้มเหลวขึ้นอยู่กับสิ่งที่ file.txt มีอยู่
Timo Salmi

0

หมายเหตุวิธีการแบตช์ไฟล์จะถูก จำกัด ไว้ที่ขีด จำกัด บรรทัดสำหรับตัวประมวลผลคำสั่ง DOS - ดูขีดจำกัดความยาวบรรทัดคำสั่งคืออะไร? .

ดังนั้นหากพยายามประมวลผลไฟล์ที่มีบรรทัดมากกว่า8192อักขระสคริปต์ก็จะข้ามไปเนื่องจากไม่สามารถเก็บค่าได้


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 ... ANYTHING ยกเว้นไฟล์. bat
paulsm4

2
แบทช์ไม่ได้แย่ขนาดนั้น (เมื่อคุณรู้สิ่งที่คุณทำเหมือนกับภาษาอื่น ๆ ) เฮ้: รหัสของคุณไม่ทำงาน
Stephan

เพราะคุณไม่ได้ใช้ส่วนขยายที่ล่าช้า
Stephan

1
@ paulsm4: ไฟล์แบตช์มีอะไรผิดปกติ? ใช้งานได้กับ Windows ทุกรสชาติและมีคุณลักษณะเฉพาะที่เรียกว่าการขยายเวลาล่าช้าทำให้เวทมนตร์เกิดขึ้นได้โดยไม่ต้องติดตั้งซอฟต์แวร์ของบุคคลที่สามตราบเท่าที่คุณเข้าใจ คุณรู้หรือไม่ว่าคุณสามารถ TCP / IP กับ DOS และไฟล์แบตช์ได้นานก่อน Powershell & dotNet
Zimba

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

-1

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

พิมพ์บรรทัดที่ 1 จากนั้นรอให้ผู้ใช้กดปุ่มเพื่อพิมพ์บรรทัดถัดไป หลังจากพิมพ์บรรทัดที่ต้องการแล้วให้กด Ctrl + C เพื่อหยุด

@Ross Presser: วิธีนี้จะพิมพ์เส้นเท่านั้นไม่ใช่นำหน้าหมายเลขบรรทัด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.