แบ่งไฟล์ย่อยสตริงออกเป็นไฟล์แยกกันโดยยึดตามตัวอักษรตัวแรก ทุบตี


4

เอาล่ะฉันมีไฟล์ที่เต็มไปด้วยสตริงนับพัน แต่ละคนอยู่ในสายของตัวเอง ฉันต้องการสร้างสคริปต์ที่จะอนุญาตให้ฉันใช้ไฟล์นี้เรียกมันlist.txtและรับไอเท็มจากแต่ละบรรทัดและวางเป็นไฟล์แยกกันตามตัวอักษรหรือตัวเลขตัวแรก ตัวอย่างเช่นสมมติว่าสองสามบรรทัดแรกของไฟล์เป็นดังนี้:

cheese
pizza
pepperoni
lettuce
grahamCrackers
0-0Foods
chicken
lentils
1-2Items

ฉันต้องการที่จะทำลายมันลงในสิ่งเหล่านี้:

c.txt

cheese
chicken

g.txt

grahamCrackers

l.txt

lettuce
lentils

p.txt

pizza
pepperoni

0.txt

0-0Foods

1.txt

1-2Items

ฉันต้องการทำสิ่งนี้ด้วย BASH บน OS X ขอบคุณ

โอ้ถ้าช่วยได้ รายการในแต่ละบรรทัดจะไม่มีที่ว่างพวกมันจะถูกบรรจุเป็นหนึ่งคำเสมอ EG (ไม่มีซุปไก่แทนซุปไก่)

คำตอบ:


4

ลองสิ่งนี้

OLDIFS=$IFS
IFS='
'
typeset -a file
file=($(cat list.txt))
for i in "${file[@]}"; do
    echo $i >> ${i:0:1}.txt
done
IFS=$OLDIFS

หมายเหตุส่วน IFS มักไม่จำเป็น นอกจากนี้ฉันทดสอบบน Zsh 4.3.17 บน linux และ Bash 4.2.37

มันทำอะไรคือการประกาศอาร์เรย์กำหนดเนื้อหาของไฟล์ให้กับอาร์เรย์นั้นจากนั้นวนซ้ำแต่ละองค์ประกอบของอาร์เรย์ดังนั้นแต่ละบรรทัดและ echo ขององค์ประกอบนั้นลงในไฟล์ด้วยชื่อของ lettes แรกบวก '.txt' ผนวกเข้ากับมัน


ฉันลองใช้รหัสที่แน่นอนนั้นและแทนที่ list.txt ด้วยไฟล์ของฉัน อย่างไรก็ตามมันใช้เวลาซักพัก แต่หลังจากนั้นก็เสร็จ ไม่มีอะไรเกิดขึ้น. ฉันคิดว่าจะทำอย่างอื่นหรือไม่?
โยสิยาห์

ไม่มันใช้งานได้สำหรับฉันนอกกรอบ ลอง 'set -x' และจากนั้นเรียกใช้คำสั่งและ pastebin ผลลัพธ์บางทีฉันสามารถช่วยได้
KoviRobi

มีสิ่งหนึ่งที่มีวิธีที่คุณสามารถวางไฟล์ที่ส่งออกเหล่านี้ในโฟลเดอร์ก่อน
โยสิยาห์

1
ใช่ 'mkdir' โฟลเดอร์นั้นก่อนจากนั้นเปลี่ยน '$ {i: 0: 1} .txt' เป็น 'โฟลเดอร์ / $ {i: 0: 1} .txt'
KoviRobi

3
โอ้โห ... นี่มันเยี่ยมกว่า grep / sed-based solution ฉันจะเขียนขึ้นมา มันน่าประหลาดใจอยู่เสมอว่าสิ่งที่ทุบตีสามารถทำได้ด้วยตัวเอง ด้วยที่กล่าวว่าคุณสามารถหลีกเลี่ยงการยุ่งกับ $ IFS และโดยทั่วไปจะทำให้สิ่งต่าง ๆ ง่ายขึ้นโดยใช้การวนรอบสักครู่แทนการวนซ้ำ แทนที่for i in "${file[@]}"; doด้วยwhile read i; doและแทนที่doneด้วยdone <list.txtจากนั้นคุณสามารถทิ้งสิ่งของทั้งหมดที่อยู่นอกลูป
evilsoup

5

คุณสามารถใช้เพ่งพิศและทำให้สิ่งต่าง ๆ :

gawk '{n=substr($1,0,1); print >> n".txt"}' file.txt
  • n=substr($1,0,1)จะใช้เวลาย่อยของความยาว 1 เริ่มต้นจากตำแหน่งแรก (0) ของสนามแรก (ก$1) nและบันทึกลงในตัวแปรที่เรียกว่า

  • print >> n".txt"จะต่อท้าย ( >>) แต่ละบรรทัดในไฟล์ข้อความที่เรียกว่าn.txt(โดยที่nตัวอักษรตัวแรก)

หากต้องการทำสิ่งเดียวกันสำหรับตัวอักษรสองตัวแรกเพียงแค่เปลี่ยนความยาวของsubstr:

gawk '{n=substr($1,0,2); print >> n".txt"}' file.txt

เยี่ยมนี่เป็นคำตอบที่ดีเช่นกัน +1!
โยสิยาห์

อย่าลืมclose()ว่าawkข้อผิดพลาด "ไฟล์เปิดค้างอยู่มากเกินไป" เช่นgawk '{n=substr($1,0,2); print >> n".txt"; close(n".txt")}' file.txt
aff

0
#!/bin/bash

while read line
do
    firstChar=${line:0:1}
    fileName=${firstChar}.txt
    if [ -e ${fileName} ];then
    touch ${fileName}
     fi
    echo ${line} >> ${fileName}
done < list.txt

สคริปต์ด้านบนใช้อักขระตัวแรกของแต่ละบรรทัดที่อ่านจากlist.txtไฟล์ จากนั้นจะพยายามสร้างไฟล์ด้วยอักขระ + ".txt" จากนั้นต่อท้ายแต่ละบรรทัดจากlist.txtไปยังไฟล์อักขระ + ".txt" ที่เหมาะสม


คุณไม่จำเป็นต้องสร้างไฟล์อย่างชัดเจน >>จะสร้างมันถ้ามันไม่ได้อยู่ (ยกเว้นกรณีที่noclobberมีการตั้งค่าในกรณีที่ไม่มีการตั้งค่าสำหรับการสคริปต์)
อเล็กซิส

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