ฉันต้องใส่ตัวแปร 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()
ใช้ตัวเรียกใช้ตัวเชื่อมโยงและตัวโหลด (ถ้าใช้ไลบรารีที่ใช้ร่วมกันซึ่งมักเป็นกรณี) ฯลฯ