ฉันต้องใส่ตัวแปร bash ในบรรทัดแรกของไฟล์ ฉันเดาว่าเป็นคำสั่ง grep แต่มีวิธี จำกัด จำนวนบรรทัดหรือไม่?
ฉันต้องใส่ตัวแปร bash ในบรรทัดแรกของไฟล์ ฉันเดาว่าเป็นคำสั่ง grep แต่มีวิธี จำกัด จำนวนบรรทัดหรือไม่?
คำตอบ:
headใช้บรรทัดแรกจากไฟล์และ-nพารามิเตอร์สามารถใช้เพื่อระบุจำนวนบรรทัดที่จะแตก:
line=$(head -n 1 filename)
line="$(head -1 FILENAME)"
line=`head -1 FILENAME`
head...เปิด subshell เหมือน$()หรือไม่?
$()ไวยากรณ์ดูง่ายกว่าและเห็นคุณค่าของความกระจ่างชัดยิ่งขึ้น gnu.org/software/bash/manual/html_node/…
หากต้องการอ่านบรรทัดแรกโดยใช้ bash ให้ใช้readคำสั่ง เช่น
read -r firstline<file
firstline จะเป็นตัวแปรของคุณ (ไม่จำเป็นต้องมอบหมายให้คนอื่น)
cat ... | read VARจะล้มเหลวในเชลล์ส่วนใหญ่ (ทั้งหมดยกเว้นzshเท่าที่ฉันรู้) เพราะแต่ละคอมโพเนนต์ในไพพ์จะทำงานในเชลล์ย่อยแยกกัน ความหมายที่$VARจะถูกตั้งค่าใน subshell (ที่หยุดอยู่ทันทีที่ไพพ์ไลน์เสร็จสิ้นการดำเนินการ) แทนที่จะอยู่ในเชลล์ที่เรียกใช้ คุณสามารถหลีกเลี่ยงปัญหานี้ได้ด้วยread VAR <<EOF\n$(cat ...)\nEOF(โดยที่แต่ละ\nบรรทัดขึ้นบรรทัดใหม่)
catเป็นค่าใช้จ่ายที่บริสุทธิ์ มีประสิทธิภาพมากขึ้นเพื่อread -r var <fileกว่าcat file | readแต่อย่างใดแม้ถ้าหลังไม่ได้ล้มเหลวด้วยเหตุผลที่อธิบายไว้ในBashFAQ #
catนี้read -r var < <(otherprog ...)
พอเพียงนี้และเก็บบรรทัดแรกของfilenameในตัวแปร$line:
read -r line < filename
ฉันก็ชอบawkสิ่งนี้:
awk 'NR==1 {print; exit}' file
ในการจัดเก็บบรรทัดให้ใช้var=$(command)ไวยากรณ์ ในกรณีline=$(awk 'NR==1 {print; exit}' file)นี้
หรือแม้กระทั่งsed:
sed -n '1p' file
line=$(sed -n '1p' file)ด้วยเทียบเท่า
ดูตัวอย่างเมื่อเราป้อนreadด้วยseq 10นั่นคือลำดับของตัวเลขจาก 1 ถึง 10:
$ read -r line < <(seq 10)
$ echo "$line"
1
$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1
sed '1!d;q'(หรือsed -n '1p;q') จะเลียนแบบawkตรรกะของคุณและป้องกันการอ่านเพิ่มเติมลงในไฟล์ เพราะเราต้องการแค่บรรทัดแรกเท่านั้นเราสามารถโกงsed qหรือawk '1;{exit}'หรือแม้แต่grep -m1 ^(รหัสน้อยกว่าตรรกะที่จำเป็นเดียวกัน) (นี่ไม่ใช่คำตอบสำหรับข้อสงสัย downvote)
grepที่ฉลาดมาก แน่นอนเราสามารถพูดhead -n 1 fileได้
head -n1จะเร็วขึ้น (ไบนารีที่เล็กกว่าสำหรับโหลด) และreadจะเร็วที่สุด (ไม่มีไบนารีสำหรับโหลดนั่นคือบิวด์อิน) ฉันชอบโดยเฉพาะอย่างยิ่งgrep -m1 --color .เมื่อฉันเพิ่งพิมพ์บรรทัดแรกเพราะมันจะทำให้สีของเส้นเกินไปทำให้ดีสำหรับส่วนหัวของตาราง
line=$(head -1 file)
จะทำงานได้ดี (ตามคำตอบก่อนหน้า) แต่
line=$(read -r FIRSTLINE < filename)
จะเร็วขึ้นเล็กน้อยเช่นเดียวกับreadคำสั่ง bash ในตัว
readไม่ได้พิมพ์อะไรเลย ( lineเว้นว่างไว้) และดำเนินการใน subshell (ดังนั้นFIRSTLINEได้รับการตั้งค่าเป็นบรรทัดแรก แต่เฉพาะใน subshell ดังนั้นจึงไม่สามารถใช้งานได้ในภายหลัง) วิธีแก้ปัญหา: ใช้เพียงread -r line <filename
เพียงechoรายการแรกของไฟล์ต้นฉบับของคุณลงในไฟล์เป้าหมายของคุณ
echo $(head -n 1 source.txt) > target.txt
head -n 1 source.txt > target.txtจะทำสิ่งเดียวกันให้สำเร็จ
คำถามไม่ได้ถามว่าคำถามใดเร็วที่สุด แต่เพื่อเพิ่มคำตอบที่น่าเบื่อ -n '1p' ทำงานได้ไม่ดีเนื่องจากพื้นที่รูปแบบยังคงสแกนในไฟล์ขนาดใหญ่ จากความอยากรู้ฉันพบว่า 'หัว' ชนะเหนือความอดกลั้น:
# best:
head -n1 $bigfile >/dev/null
# a bit slower than head (I saw about 10% difference):
sed '1q' $bigfile >/dev/null
# VERY slow:
sed -n '1p' $bigfile >/dev/null
readวิธีการ$()แยกออกจาก subshell และการใช้คำสั่งภายนอก (คำสั่งภายนอกใด ๆ ) หมายความว่าคุณกำลังเรียกexecve()ใช้ตัวเรียกใช้ตัวเชื่อมโยงและตัวโหลด (ถ้าใช้ไลบรารีที่ใช้ร่วมกันซึ่งมักเป็นกรณี) ฯลฯ