แทนที่ช่องว่างหลายช่องด้วยช่องว่างโดยใช้ 'tr' เท่านั้น


71

ฉันมีไฟล์f1.txt:

ID     Name
1      a
2         b
3   g
6            f

จำนวนช่องว่างไม่คงที่ วิธีที่ดีที่สุดในการแทนที่ช่องว่างสีขาวทั้งหมดด้วยช่องว่างเดียวใช้เพียงtrใด

นี่คือสิ่งที่ฉันมี:

cat f1.txt | tr -d " "

แต่ผลลัพธ์คือ:

IDName
1a
2b
3g
6f

แต่ฉันต้องการให้มันเป็นเช่นนี้:

ID Name
1 a
2 b
3 g
6 f

sedโปรดลองและหลีกเลี่ยง


6
ทำไมจึงเป็นเรื่องสำคัญอย่างยิ่งที่จะหลีกเลี่ยงความไม่สะดวก ใช้งานอะไรก็ได้!
David Richerby

7
sedเพราะฉันรู้ว่าวิธีการที่จะทำมันด้วย อยากรู้วิธีอื่น ๆ
:)

คำตอบ:


106

ด้วยtrใช้ตัวเลือกการทำซ้ำsqueeze :

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

หรือคุณสามารถใช้awkโซลูชัน:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

เมื่อคุณเปลี่ยนฟิลด์ในบันทึกให้awkสร้างใหม่$0นำฟิลด์ทั้งหมดและต่อเข้าด้วยกันคั่นด้วยOFSซึ่งเป็นช่องว่างตามค่าเริ่มต้น

ที่จะบีบลำดับของช่องว่างและแท็บ (และอักขระว่างอื่น ๆ อาจขึ้นอยู่กับสถานที่และการนำไปใช้awk) ลงในหนึ่งช่องว่าง แต่ยังลบช่องว่างด้านหน้าและด้านหลังออกแต่ละบรรทัด


1
นี่เป็นทางออกที่ดีเช่นกัน . . ฉันไม่รู้ว่าจะเลือกอันไหนในตอนนี้: / @Gnouc
gkmohit

รู้สึกอิสระที่จะเลือกวิธีการแก้ปัญหาใด ๆ ที่คุณชอบและมันเหมาะกับคุณ โปรดทราบว่าการแก้ปัญหาของฉันแตกต่างกับคำตอบของ @ polym
cuonglm

1
:)) เย้! คำตอบของ @Gnouc นั้นเป็นแบบไดนามิกจริงๆเพราะเขาใช้awkเขาสามารถทำอะไรก็ได้ คุณสามารถยอมรับคำตอบของเขาได้ มีเพียงสิ่งเดียว: Gnouc คุณสามารถอธิบายรูปแบบ awk ในคำสั่งของคุณได้ไหม? นอกจากนี้คุณสามารถเพิ่มแท็บ / ช่องว่างเพื่อให้เอาต์พุตสอดคล้องกับเอาต์พุตที่ไม่คาดหมายได้หรือไม่?
polym

1
@polym: ด้วยการแก้ไขล่าสุดของ Unknown ดูเหมือนว่าเขาต้องการเพียงหนึ่งช่องว่างcolumn -tเท่านั้น awkเพิ่มคำอธิบายสำหรับ
cuonglm

4
มีความแตกต่างเล็กน้อยที่นี่ trจะแทนที่ช่องว่างสองช่องที่ท้ายบรรทัดด้วยช่องว่างเดียว awkจะลบช่องว่างต่อท้ายทั้งหมด
Anne van Rossum

19

เพียงใช้column:

column -t inputFile

เอาท์พุท:

ID  Name
1   a
2   b
3   g
6   f

การตอบกลับที่ยอดเยี่ยมและรวดเร็ว :)
gkmohit

1
@ ไม่เป็นที่รู้จักที่ดีที่จะให้บริการ :)!
polym

1
@Gnouc ว้าวเจ๋งคอลัมน์ก็ใช้ไฟล์เป็นอาร์กิวเมนต์ ขอบคุณมาก!
polym

ฉันจะรับคอลัมน์ที่สองได้อย่างไรถ้าฉันต้องการ ฉันลองแล้วcolumn -t f1.txt | cut -d " " -f2 แต่ไม่ใช่วิธีแก้ปัญหาที่ฉันคาดไว้
gkmohit

2
ใช้ awk แล้วcolumn -t file | awk '{print $2}'พิมพ์เฉพาะคอลัมน์ที่สองเท่านั้น
polym

8

หากคุณต้องการบีบ "ช่องว่างสีขาว" คุณจะต้องใช้ชุดอักขระที่กำหนดไว้ล่วงหน้าของ tr ": blank:" (แท็บช่องว่างตามแนวนอนและช่องว่าง) หรือ ": space:" (ช่องว่าง verical):

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

ตัวอย่างถูกเรียกใช้บน Red Hat 5 (GNU tr)

ในกรณีของฉันฉันต้องการทำให้ช่องว่างทั้งหมดเป็นปกติในพื้นที่เดียวดังนั้นฉันจึงสามารถพึ่งพาพื้นที่เป็นตัวส่ง

ตามที่ระบุไว้โดยความคิดเห็นที่สองของ dastrobu ฉันไม่ได้ใช้ถ้อยคำในหน้า man:

 -s uses the last specified SET, and occurs after translation or deletion.

สิ่งนี้ทำให้เราสามารถกำจัด tr แรกได้ คูโดะต้องสกอตต์เพื่อความอดทนของเขาเมื่อเผชิญกับความหนาแน่นของฉัน

ก่อนทำการแยกวิเคราะห์พอร์ตจาก Redis config ไฟล์:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

หลังจากนั้นเมื่อ SET2 ถูกระบุด้วยการบีบ:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

เอาท์พุท:

6379

สำหรับรายละเอียดเพิ่มเติมที่ครอบคลุมความแตกต่างของช่องว่าง

แสดงให้เห็นว่าการบีบตัวคนเดียวล้มเหลวเมื่อตัวละครผสมต่อเนื่องซึ่งตกอยู่ในคลาสตัวละคร [: blank:] เกี่ยวข้อง:

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

หมายเหตุ: สองฟิลด์สตริงของฉันในรูปแบบ printf คั่นด้วย 1 ช่องว่างแท็บ 1 ช่องว่าง 1 ช่อง หลังจากบีบลำดับนี้ยังคงมีอยู่ ในผลลัพธ์ของการดัมพ์ Octal สิ่งนี้แสดงโดยลำดับ ascii 040 011 040


1
คุณต้องการจริงๆtr "[:blank:]" " " | tr -s "[:blank:]"เหรอ? ฉันเดาว่าส่วนแรกจะพอเพียงนั่นคือtr "[:blank:]" " "เนื่องจากมันทำให้ช่องว่างเป็นปกติและทำการทดแทนแล้ว จากหน้าเว็บมนุษย์: "บีบอักขระจำนวนมากที่เกิดขึ้น [... ] เหตุการณ์นี้เกิดขึ้นหลังจากการลบและการแปลทั้งหมดเสร็จสิ้น"
dastrobu

2
ดังนั้น´tr -s "[: blank:]" "" ´ควรทำมันก่อนแปลช่องว่างทั้งหมดเป็นช่องว่างแล้วบีบช่องว่าง ไม่จำเป็นต้องใช้´tr´ ตัวที่สอง
dastrobu

1
ฉันพยายามprintf 'ID \t Name\n' | tr -s "[:blank:]" " " | od -cb(ตามที่แนะนำโดย @dastrobu) และฉันได้รับID Name\n(มีที่ว่างหนึ่งอัน ) เป็นเอาต์พุต คุณลองใช้งานจริงหรือไม่ @ user3183018
สกอตต์

1
ตกลงให้ฉันลองพูดอีกครั้ง ฉันทำprintf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"  (ตามที่แนะนำโดย @dastrobu) ซึ่งแทนช่องว่างและฉันได้รับID␣Name\n(ด้วยช่องว่างหนึ่งช่อง) เป็นผลลัพธ์ นี่เป็นตัวอย่างเดียวกับตัวอย่างของคุณ “ Port <SPACE> <TAB> <SPACE> 6379” ยกเว้นว่าฉันใช้สตริงหัวเรื่องจากคำถาม ฉันสงสัยว่าคุณลองแล้วหรือยัง  tr -s "[:blank:]"(โดยไม่มี"␣"ข้อโต้แย้งสุดท้าย)
สกอตต์

1
เมื่อฉันทำprintf 'ID \t Name\n' | od -cbมันจะแสดงสิ่งที่ควรจะเป็น: ID ⁠  \t ⁠  N a m e \n(เช่น  ID 040 011 040 N a m e\n) ขณะเดียวกันจากหลักฐานของคุณเองคุณกำลังทำว่าข้อผิดพลาดที่ผมเดาว่าคุณ: คุณกำลังใช้งานtr -s "[:blank:]"(เช่น  trกับหนึ่งในตัวเลือกและ  หนึ่งอาร์กิวเมนต์) แทนคำสั่งที่ @dastrobu และผมได้นำเสนอครั้งที่สี่ในขณะนี้: tr -s '[:blank:]' '␣'(เช่น  trมีหนึ่งตัวเลือกและ  สองอาร์กิวเมนต์ )
สกอตต์

5

ใครต้องการโปรแกรม (นอกเหนือจากเชลล์)

while read a b
do
    echo "$a $b"
done < f1.txt

หากคุณต้องการให้ค่าในคอลัมน์ที่สองจัดเรียงเหมือนในcolumnคำตอบของ polym ให้ใช้printfแทนecho:

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt

1
ในตอนแรกเมื่อเทียบกับ tr - นี่เป็นข้อเสนอแนะที่อ่อนแออย่างมีประสิทธิภาพที่ชาญฉลาดเว้นแต่อินพุตมีขนาดเล็กเกินไปเกินดุลค่าใช้จ่ายในtrการขอร้องน้อยมาก สุดท้ายคุณจะไม่พูดว่าโพสต์นี้ไม่ตอบคำถามตามที่ถามจริงหรือ วิธีที่ดีที่สุดในการแทนที่ช่องว่างสีขาวทั้งหมดด้วยช่องว่างเดียวโดยใช้ tr คืออะไร
mikeserv

1
และนอกจากนี้คุณไม่สามารถทำอะไรกับมันได้ง่ายกว่านี้อีก$IFSหรือ อาจจะต้องการ: IFS=' <tab>' set -f ; echo $(cat <file)?
mikeserv

2

นี่เป็นคำถามเก่าและแก้ไขได้หลายครั้ง เพียงเพื่อความสมบูรณ์: ฉันมีปัญหา simillar แต่ต้องการที่จะผ่านเส้นผ่านท่อไปยังโปรแกรม antother ผมใช้xargs

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

ดังนั้นcat f1.txt | xargs -L1ดูเหมือนว่าจะส่งออกสิ่งที่คุณต้องการ

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