รับแค่จำนวนเต็มจาก wc ใน bash


115

มีวิธีรับจำนวนเต็มที่ wc ส่งคืนเป็น bash หรือไม่?

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

output: filename linecount wordcount นี่คือสิ่งที่ฉันมีจนถึงตอนนี้:

files=`ls`
for f in $files;
do
        if [ ! -d $f ] #only print out information about files !directories
        then
                # some way of getting the wc integers into shell variables and then printing them
                echo "$f $lines $ words"
        fi
done

คำตอบ:


58

คุณสามารถใช้cutคำสั่งเพื่อรับเพียงคำแรกของwcผลลัพธ์ (ซึ่งเป็นบรรทัดหรือจำนวนคำ):

lines=`wc -l $f | cut -f1 -d' '`
words=`wc -w $f | cut -f1 -d' '`

5
การรัน wc สองครั้งสำหรับไฟล์เดียวกันนั้นไม่มีประสิทธิภาพ
กาวี

3
จริงอยู่นั่นคือเหตุผลที่ฉันคิดว่าคำตอบของ James Broadhead นั้นดีกว่ามาก ฉันไม่cutสามารถทำงานกับผลลัพธ์ทั้งหมดได้wc $fเนื่องจากจำนวนช่องว่างระหว่างฟิลด์แตกต่างกันไป
คาซาบลังกา

1
@casablanca คุณสามารถบีบจำนวนช่องว่างโดยใช้ "tr -s" ฉันได้ระบุวิธีแก้ปัญหาแบบพกพาเพิ่มเติมสำหรับคำถามนี้ไว้ในคำตอบด้านล่าง
รูเบิล

เนื่องจากในคำตอบนี้เรากำหนดให้กับตัวแปรเราสามารถฆ่าช่องว่างด้วย
cycollins

88

คำตอบที่ง่ายที่สุดที่เคยมีมา:

wc < filename 

5
แต่ไม่ได้สร้างผลลัพธ์ที่ต้องการ
Dave Newton

แน่นอนคุณเพียงแค่ส่งผ่านพารามิเตอร์ที่เหมาะสมที่คุณจะทำต่อไป ตัวอย่างเช่นถ้าคุณทำwc -c < file nameมันจะให้คุณเป็นเพียงจำนวนเต็มของไบต์และไม่มีอะไรอื่น
BananaNeil

13
ประเด็นของฉันคือถ้าคุณจะตอบคำถาม (อายุ 1.5 ปี) อาจใส่ข้อมูลทั้งหมดลงในคำตอบนั่นคือทั้งหมด :)
Dave Newton

ขออภัยเพียงอีกครั้งอ่านคำถาม .. #fail ฉันค้นคว้าวิธีการที่จะได้รับเพียงจำนวนเต็มและผมใช้ข้อมูลจากหนึ่งในคำตอบเมื่อฉันค้นพบคำตอบที่ดีและจากนั้นตัดสินใจที่จะโพสต์เกี่ยวกับเรื่องนี้ ขอโทษ ..
BananaNeil

3
คุณตอบ Google แล้วนั่นคือสิ่งที่มีค่า :-)
Ciro Santilli 郝海东冠状病六四事件

82

แค่:

wc -l < file_name

จะทำงาน แต่เอาท์พุทนี้มีช่องว่างที่นำหน้าเป็นชิดwcขวาของตัวเลข


3
หากต้องการนับเส้นโดยไม่ต้องเว้นวรรค: wc -l < foo.txt | xargsref - stackoverflow.com/a/12973694/149428
Taylor Edmiston

1
ดังนั้นในขณะที่คำสั่งสร้างคำตอบด้วยช่องว่างนำหน้าผู้ถามกำลังกำหนดให้กับตัวแปรและจะลดช่องว่างนำหน้าโดยอัตโนมัติ (อย่างน้อยนั่นก็เป็นประสบการณ์ของฉันใน OSX bash รุ่นเก่า) กล่าวอีกนัยหนึ่งคือlines=`wc -l < $f`ผลลัพธ์ในตัวแปร "เส้น" ที่ค่าไม่มีช่องว่างนำหน้า
cycollins

จะเกิดอะไรขึ้นถ้าฉันวางท่อด้วย find? ฉันได้รับข้อผิดพลาด: ใช้ find . -path -prune -o -name "*.swift" -print0 | xargs -0 wc -lงานได้ดี แต่พิมพ์ทุกไฟล์ หากฉันใช้find . -path -prune -o -name "*.swift" -print0 | xargs -0 wc -l <ฉันได้รับข้อผิดพลาด parse error near '\n'
Nuno Gonçalves

55
wc $file | awk {'print "$4" "$2" "$1"'}

ปรับตามความจำเป็นสำหรับเค้าโครงของคุณ

นอกจากนี้ยังดีกว่าที่จะใช้ตรรกะเชิงบวก ("เป็นไฟล์") กับค่าลบ ("ไม่ใช่ไดเรกทอรี")

[ -f $file ] && wc $file | awk {'print "$4" "$2" "$1"'}

1
บน Windows ของฉันใน Cmder (bash 4.4.12) สิ่งนี้ใช้ได้: wc $file | awk '{print $4" "$2" "$1}'- เครื่องหมายวรรคตอนที่อยู่นอก{}ไฟล์.
Grzegorz Gierlik

36

บางครั้ง wc จะแสดงผลในรูปแบบที่แตกต่างกันในแพลตฟอร์มต่างๆ ตัวอย่างเช่น:

ใน OS X:

$ echo aa | wc -l

         1

ใน Centos:

$ echo aa | wc -l

1

ดังนั้นการใช้การตัดเพียงอย่างเดียวอาจไม่ได้รับหมายเลข ลอง tr เพื่อลบอักขระเว้นวรรคแทน:

$ echo aa | wc -l | tr -d ' '

23

คำตอบที่ยอมรับ / เป็นที่นิยมใช้ไม่ได้บน OSX

สิ่งต่อไปนี้ควรพกพาได้บน bsd และ linux

wc -l < "$f" | tr -d ' '

หรือ

wc -l "$f" | tr -s ' ' | cut -d ' ' -f 2

หรือ

wc -l "$f" | awk '{print $1}'

11

หากคุณเปลี่ยนเส้นทางชื่อไฟล์เข้าไปwcจะละเว้นชื่อไฟล์บนเอาต์พุต

ทุบตี:

read lines words characters <<< $(wc < filename)

หรือ

read lines words characters <<EOF
$(wc < filename)
EOF

แทนที่จะใช้forเพื่อทำซ้ำบนผลลัพธ์ของlsให้ทำสิ่งนี้:

for f in *

ซึ่งจะใช้งานได้หากมีชื่อไฟล์ที่มีช่องว่าง

หากคุณไม่สามารถใช้ globbing ได้คุณควรต่อท่อเป็นwhile readวง:

find ... | while read -r f

หรือใช้การทดแทนกระบวนการ

while read -r f
do
    something
done < <(find ...)

ฉันโหวตให้คุณแล้ว แต่คุณไม่จำเป็นต้องเปลี่ยนเส้นทางชื่อไฟล์ เพียงแค่จับมันเป็นฟิลด์เพิ่มเติม read lines words characters filename <<< $(wc "$f")อ้อและถ้าคุณใช้ * ชุบแข็งกับช่องว่างคุณก็ต้องใส่เครื่องหมาย var สองครั้งเมื่อใช้ด้วย
Bruno Bronosky

การใช้ตัวแปรเพิ่มเติมเป็นอีกวิธีหนึ่งที่จะทำได้ แต่ถ้าคุณจะไม่ใช้ตัวแปร (บางทีคุณอาจมีชื่อไฟล์ในตัวแปร - $fในกรณีนี้) ก็ไม่จำเป็น นอกจากนี้ OP ยังขอวิธีรับแค่จำนวนเต็ม คุณพูดถูกต้องเกี่ยวกับการอ้างถึงตัวแปร แต่ฉันไม่ได้แสดงการใช้ตัวแปรดังนั้นฉันจึงไม่พูดถึงประเด็นนั้น for f in *รูปแบบควรมักจะถูกนำมาใช้แทนการใช้การส่งออกของlsที่คุณรู้ว่า
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

ฉันเห็นด้วยอย่างสมบูรณ์ในlsประเด็นนี้ นั่นจะทำให้คุณได้รับรางวัล partmaps.org/era/unix/award.html#ls
Bruno Bronosky

หากคุณไม่ต้องการชื่อไฟล์คุณสามารถทำได้:read lines words characters _ <<< $(wc "$f")

@EvanTeitelman: ตามที่กล่าวไว้ในสองความคิดเห็นด้านบนของคุณ $_เป็นเพียงตัวแปรที่แตกต่างกัน
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

3

หากไฟล์มีขนาดเล็กคุณสามารถโทรได้wcสองครั้งและใช้สิ่งต่อไปนี้เพื่อหลีกเลี่ยงการส่งต่อไปยังกระบวนการเพิ่มเติม:

lines=$((`wc -l "$f"`))
words=$((`wc -w "$f"`))

$((...))คือการขยายตัวทางคณิตศาสตร์ของทุบตี จะลบช่องว่างใด ๆ ออกจากผลลัพธ์ของwcในกรณีนี้

วิธีนี้เหมาะสมกว่าหากคุณต้องการทั้ง linecount หรือ wordcount





0

ลองสิ่งนี้:

wc `ls` | awk '{ LINE += $1; WC += $2 } END { print "lines: " LINE  " words: " WC }'

สร้างจำนวนบรรทัดและจำนวนคำ (LINE และ WC) และเพิ่มค่าด้วยค่าที่ดึงมาจาก wc (โดยใช้ $ 1 สำหรับค่าของคอลัมน์แรกและ $ 2 สำหรับวินาที) และสุดท้ายจะพิมพ์ผลลัพธ์


0

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

answer=(`wc $f`)
echo -e"${answer[3]}
lines:  ${answer[0]}
words:  ${answer[1]}
bytes:  ${answer[2]}"

เอาต์พุต: myfile.txt บรรทัด: 10 คำ: 20 ไบต์: 120


0
files=`ls`
echo "$files" | wc -l | perl -pe "s#^\s+##"

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