วิธีแทนที่ช่องว่างหลายช่องด้วยแท็บเดียว


27

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


ขอบคุณสำหรับการป้อนข้อมูลที่ดี แต่ฉันมีช่องว่างเดียวภายในคอลัมน์ดังนั้นฉันต้องหลีกเลี่ยงการแท็บพื้นที่เดียว ขอโทษสำหรับข้อมูลนั้น
user_unknown

คำตอบ:


31

หากต้องการแปลงลำดับมากกว่าหนึ่งช่องว่างให้กับแท็บ แต่เว้นช่องว่างแต่ละรายการ :

sed 's/ \+ /\t/g' inputfile > outputfile

เมื่อต้องการทำสิ่งนี้กับไฟล์จำนวนหนึ่ง:

for inputfile in *
do
    sed 's/ \+ /\t/g' "$inputfile" > tmpfile && mv tmpfile "$inputfile"
done

หรือ

for inputfile in *
do
    sed -i.bak 's/ \+ /\t/g' "$inputfile"
done

หรือ

find . -type f -exec sed -i.bak 's/ \+ /\t/g' {} \;

sed: -e expression #1, char 1: unknown command: `.'
Aaron Franke

@AaronFranke: คุณลองใช้คำสั่งอะไร? ตัวอย่างในคำตอบของฉันไม่ควรสร้างข้อผิดพลาดนั้น
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

ขออภัยฉันควรจะชี้แจง ด้านfindหนึ่งอยู่ด้านล่าง
Aaron Franke

@AaronFranke: GNU sedไม่ต้องการมีช่องว่างก่อนส่วนขยายการสำรองข้อมูล ฉันแก้ไขคำตอบของฉันแล้ว ขอบคุณสำหรับการรายงาน
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

7

หากตัวละครของคุณเป็นหลายแท็บคุณสามารถใช้tr -s:

-s, --squeeze-repeats   replace each input sequence of a repeated character
                        that is listed in SET1 with a single occurrence

ตัวอย่างเช่น:

my_file.txt | tr -s " "

ช่องว่างสีขาวทั้งหมดจะกลายเป็นหนึ่งเดียว


นี่ไม่ใช่สิ่งที่ OP ขอมา
RonJohn

5

คุณสามารถใช้sedเพื่อแทนที่จำนวนช่องว่างด้วยแท็บ:

ตัวอย่างเพื่อแทนที่ช่องว่างหนึ่งหรือมากกว่าด้วยหนึ่งแท็บ:

cat spaced-file | sed 's/ \+/\t/g' > tabbed-file

OP กล่าวว่าจำนวนของช่องว่างเป็นตัวแปรดังนั้นฉันไม่คิดว่าวิธีนี้จะใช้งานได้
มิเคล

@Mikel อุ่ย ขอบคุณสำหรับการชี้ให้เห็นว่า ฉันแก้ไขโพสต์เพื่ออนุญาตการจับคู่สำหรับช่องว่างของตัวแปร
IvanGoneKrazy

คำตอบที่มีประโยชน์ที่สุดที่นี่
Luís de Sousa

3

คำตอบที่ง่ายที่สุดที่ใช้เพียงอย่างเดียวbashคือ:

while read -r col1 col2 col3 ...; do
    echo -e "$col1\t$col2\t$col3..."
done <file

หากมีจำนวนตัวแปรของคอลัมน์คุณสามารถทำเช่นนี้ แต่มันจะทำงานในbashไม่sh:

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <file

เช่น

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <<EOF
a b   c
d   e    f
  g h i
EOF

ผลิต:

a   b   c
d   e   f
g   h   i

(มีแท็บอยู่ระหว่างแต่ละอัน แต่มันยากที่จะเห็นเมื่อฉันวางไว้ที่นี่)

คุณสามารถทำได้โดยใช้sedหรือtrแต่สังเกตว่าการจัดการช่องว่างเมื่อเริ่มต้นให้ผลลัพธ์ที่แตกต่างกัน

sed:

$ sed 's/  */\t/g' << EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i

tr:

$ tr -s ' ' '\t' <<EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i


2

ลองใช้สคริปต์ SED ต่อไปนี้:

 sed 's/  */<TAB>/g' <spaces-file > tabs-file

ที่ <TAB> กำลังกดปุ่ม TAB


0

นี่เป็นวิธีแก้ปัญหาที่ง่ายมาก:

    sed -E 's/\s+/\t/g' your_file > new_file

sed โดยพื้นฐานแล้วทำงานในลักษณะนี้ (sed 's / old_pattern / new_pattern / g') ในกรณีนี้รูปแบบเก่าคือ "\ s +" ซึ่งหมายถึงค้นหาช่องว่าง "s" หนึ่งครั้งหรือมากกว่า "+" และเครื่องหมายทับด้านหลัง "\" เพื่อตีความว่าเป็นนิพจน์ทั่วไป
รูปแบบใหม่คือแท็บ "\ t" ซึ่งเขียนในรูปแบบนิพจน์ทั่วไปและ "g" ใช้การแทนที่ทุกบรรทัด "ทั่วโลก"


1
สวัสดีและยินดีต้อนรับสู่ superuser คุณควรใช้เวลาอธิบายวิธีแก้ปัญหาของคุณ สำหรับคนที่ไม่คุ้นเคยกับระบบ * nix, sed และนิพจน์ทั่วไปนี่ดูเหมือนกองอักขระแปลก ๆ
Mogget
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.