ฉันจะระบุบรรทัดในไฟล์ในระยะเวลาหนึ่งได้อย่างไร


12

ฉันต้องการค้นหาบรรทัดในรหัสของฉันที่มีความยาวเกินกว่าที่กำหนด รหัสของฉันมีหลายไฟล์ วิธีที่ดีในการทำเช่นนี้คืออะไร?

ฉันต้องการทราบไฟล์และหมายเลขบรรทัด เนื้อหาจะเป็นที่ต้องการ แต่ไม่จำเป็น จุดประสงค์ของการฝึกคือเพื่อหาวิธีแยกเส้น (อาจเป็นด้วยตนเอง)


คุณต้องการผลลัพธ์อย่างไร ในฐานะที่เป็นบรรทัดตัวเอง (เนื้อหาของพวกเขาในgrep) หรือเป็นหมายเลขบรรทัดหรือเป็นอย่างอื่น (บางทีคุณต้องการที่จะใช้การกระทำอื่นกับพวกเขา)? อาจเป็นวิธีที่สะดวกที่สุดในการทำเช่นนี้ขึ้นอยู่กับสิ่งที่จะทำกับบรรทัดเหล่านี้ต่อไป
imz - Ivan Zakharyaschev

@ imz - IvanZakharyaschev จุดที่ดี อัปเดตคำถามแล้ว
Marcin

คำตอบ:


13

ด้วยgrep:

grep -En '.{12}' file

สำหรับบรรทัดที่มีความยาวอย่างน้อย 12 ตัวอักษร

มีหลายไฟล์:

find . -type f -exec grep -En '.{12}' {} +

grepการใช้งานบางอย่างเช่น GNU grepสามารถค้นหาไฟล์ได้ด้วยตนเอง

grep -rEn '.{12}' .

แต่ระวัง symlink และไฟล์อื่น ๆ ที่ไม่ปกติ


ฉันชอบสิ่งนี้เพราะมันเรียบง่ายและฉันหวังว่าจะทำอะไรแบบนี้ (ยังไม่ได้รับรอบ)
Marcin

12

โซลูชัน AWK

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

หรือรัดกุมมากขึ้น:

awk 'length > 5' file

9
เราสามารถย่อรุ่นของคุณให้สั้นลงawk 'length > 5'
cuonglm

Gnouc เป็นฆาตกรรั้ง;)
Ouki

1
+1 สำหรับawk 'length > 5'

3
ด้วย GNU awkความหรูหราที่ค่อนข้างน้อย แต่รัดกุมawk '/^.{6,}/'
iruvar

3
@ 1_CR นั่นคือ POSIX และสามารถย่อให้สั้นลงได้awk '/.{6}/'(จริง ๆ แล้ว GNU awk จนกระทั่งเมื่อเร็ว ๆ นี้เคยเป็นคนหนึ่งที่ไม่สามารถทำงานได้เว้นแต่คุณจะผ่าน POSIXLY_CORRECT ไปยังสภาพแวดล้อมของมัน)
Stéphane Chazelas


5

Bash solution

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

./whatever.sh < input.fileดังนั้นเช่น สิ่งนี้ไม่รวมถึงการขึ้นบรรทัดใหม่ด้วยการลบ 1 จาก$len; หากไม่เป็นที่น่าพอใจหรือข้อมูลของคุณใช้ตอนจบ CRLF คุณควรปรับเปลี่ยนให้เหมาะสม


1
ทำไมไม่${#line}หลีกเลี่ยงexprทางแยกล่ะ?
iruvar

1
ฮ่า, +1 สำหรับbashวิธีแก้ปัญหาที่บริสุทธิ์ แต่โปรดทราบว่าหากคุณไม่ติดIFS=อยู่ข้างหน้าreadช่องว่างนำหน้าจะถูกละเว้น
iruvar

1
เพิ่มในแนวทางปฏิบัติที่ดีทุบตีไม่กี่ นอกจากนี้โปรดทราบว่าบรรทัดใหม่ไม่ได้ถูกนำมาใช้$lineดังนั้นจึงไม่จำเป็นต้องลบออก
iruvar

2
@ 1_CR จริง ๆ แล้วถ้าคุณไม่มีreadชื่อให้อ่านมันจะอ่านREPLYและรวมช่องว่างทั้งหมด ไม่IFSจำเป็นต้องตั้งค่าใด ๆ
kojiro

2
นั่นจะช้ามากและจัดการแบ็กสแลชอักขระพิเศษ while readการวนลูปไปยังข้อความเป็นสิ่งที่ปฏิบัติได้จริง
Stéphane Chazelas

4

ด้วยperl(เช่น) สมมติว่าคุณกำลังค้นหาบรรทัดที่ยาวเกิน 80 อักขระ:

ในการแสดงเส้น:

$ perl -nle 'print if length > 80' your_file

ในการแสดงหมายเลขบรรทัด:

$ perl -nle 'print "$.\n" if length > 80' your_file

หรือทั้งคู่:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file

3
คุณควรเพิ่ม-lบรรทัดคำสั่งperlจะนับการแบ่งบรรทัดในบรรทัดของคุณ
cuonglm


1

นี่เป็นอีกวิธีแก้ปัญหาทุบตี (ทุบตี 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

อาเรย์ที่เกิดขึ้นนั้นกระจัดกระจายดังนั้นดัชนีอาเรย์จึงถูกเก็บรักษาไว้ ตั้งแต่เราเริ่มต้นที่ 1 ดัชนีคือหมายเลขบรรทัดของบรรทัดที่เราเก็บไว้ เราสามารถส่งออกเฉพาะหมายเลขบรรทัดเหล่านั้น:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

หรือเราสามารถเอาท์พุทเส้นเองได้:

printf '%s\n' "${MAPFILE[@]}"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.