Regex เพื่อแทนที่ช่องว่างหลายช่องด้วยช่องว่างเดียว


510

รับสายเหมือน:

"สุนัขมีหางยาวและเป็นสีแดง!"

jQuery หรือ JavaScript ชนิดใดที่สามารถใช้ในการรักษาช่องว่างให้มีพื้นที่สูงสุดได้เพียงหนึ่งช่องเท่านั้น

เป้าหมาย:

"สุนัขมีหางยาวและเป็นสีแดง!"

4
คุณต้องการจับคู่ตัวละครในแท็บ whitespacy หรือไม่?
คริสชาวนา

@ Chris, ใช่โปรดคำถามที่ดี .... ด้วยคำตอบที่แตกต่างกันเหล่านี้เป็นวิธีการหนึ่งที่ควรรู้ว่าเป็นทางออกที่มีประสิทธิภาพที่สุด?
AnApprentice

2
ทุกคนด้านล่างถูกต้อง แต่นี่คือ regex ที่ได้รับการปรับปรุงมากที่สุด: str.replace(/ +(?= )/g,'');คุณไม่ได้แทนที่สิ่งใด ๆ
Evan Carroll

2
จะไม่มีความแตกต่างที่ชัดเจนในประสิทธิภาพ คุณสามารถโพรไฟล์ได้เสมอ แต่ฉันสงสัยว่ามันจะคุ้มค่า ฉันจะไปเพื่อที่ชัดเจนที่สุด
Draemon

@EvanCarroll: ไม่จริง - อย่างน้อยบน Firefox เวอร์ชันนั้นทำงานช้าลงอย่างมาก ดูผลลัพธ์การทำโปรไฟล์ในคำตอบของฉัน (ด้านล่าง)
Edward Loper

คำตอบ:


937

ระบุว่าคุณยังต้องการครอบคลุมแท็บบรรทัดใหม่ ฯลฯ เพียงแทนที่\s\s+ด้วย' ':

string = string.replace(/\s\s+/g, ' ');

หากคุณต้องการครอบคลุมเฉพาะช่องว่าง (และไม่ใช่แท็บบรรทัดใหม่ ฯลฯ ) ให้ทำดังนี้:

string = string.replace(/  +/g, ' ');

4
คุณต้องเพิ่มการตั้งค่าสถานะ 'g' ลงใน regex
Rafael

6
สิ่งนี้ไม่ทำงานเมื่อต้องการให้ว่างเปล่าแทนแท็บหรือขึ้นบรรทัดใหม่ ขวา? / \ s + / จะทำงาน
เฟเบียน

3
มันอาจจะดีกว่าสำหรับคุณในฐานะฟังก์ชั่นเช่นfunction removeExtraSpaces(string){ return string.replace(/\s{2,}/g, ' ');}
Math chiller

5
@Ethan: JS trim()มีฟังก์ชั่นในตัวสำหรับการที่: มันเร็วกว่า regex คุณเพียงแค่จะทำหรือstring.trim().replace(/\s\s+/g, ' '); string.replace(/\s\s+/g, ' ').trim();
BalusC

4
/\s\s+/gและ/\s{2,}/gไม่จับคู่อักขระช่องว่างเว้นเสียแต่ว่ามีอย่างน้อยสองตัวติดกันเช่นจะจับคู่ \ t \ t แต่จะไม่ตรงกับ \ t เดี่ยว string.replace(/\s+/g, ' ')จะจับคู่กับสตริงย่อยอักขระ whitespacey ทั้งหมดและหลายตัวและแทนที่ด้วยช่องว่างเดียว
remyActual

159

เมื่อคุณดูเหมือนจะสนใจในการแสดงฉันก็ทำมันด้วย firebug นี่คือผลลัพธ์ที่ฉันได้รับ:

str.replace( /  +/g, ' ' )       ->  380ms
str.replace( /\s\s+/g, ' ' )     ->  390ms
str.replace( / {2,}/g, ' ' )     ->  470ms
str.replace( / +/g, ' ' )        ->  790ms
str.replace( / +(?= )/g, ' ')    -> 3250ms

นี่คือ Firefox ใช้การแทนที่สตริง 100k

ฉันขอแนะนำให้คุณทำแบบทดสอบการทำโปรไฟล์ด้วย firebug หากคุณคิดว่าประสิทธิภาพเป็นปัญหา มนุษย์เลวร้ายในการทำนายว่าคอขวดในโปรแกรมของพวกเขาอยู่ตรงไหน

(นอกจากนี้โปรดทราบว่าแถบเครื่องมือสำหรับนักพัฒนาของ IE 8 ยังมีตัวสร้างโปรไฟล์ด้วย - มันอาจคุ้มค่าที่จะตรวจสอบว่าประสิทธิภาพการทำงานเป็นอย่างไรใน IE)


5
jsperf.com/removing-multiple-spacesออกไปและ JSPerf! วิธีสุดท้าย ( / +(?= )/g, ' ');ล้มเหลวใน IE9 มันออกจากช่องว่างสอง: "Foo Bar Baz".replace(/ +(?= )/g, ' ');->"Foo Bar Baz"
Nenotlep

มีความแตกต่างมาก bw 1 และ 2 บรรทัด
Vivek Panday

@VivekPanday - ฉันคิดว่านี่เป็นเพราะบรรทัดที่สองเป็นเพียงการแทนที่การเกิดขึ้นของช่องว่างสองครั้งด้วยช่องว่างเดียวในขณะที่ครั้งแรกคือการแทนที่ช่องว่างใด ๆ ด้วยช่องว่างเช่นกัน ไม่ว่าจะเป็นเวลาที่บันทึกในระหว่างการค้นหาหรือการแทนที่จริงฉันไม่รู้
Maloric

สิ่งนี้จะไม่ลบช่องว่างเริ่มต้นและช่องว่างต่อท้าย สำหรับที่เห็นคำตอบนี้
อีธาน

แก้ไขการสั่งซื้อโดยลดความเร็ว ความคิดเห็นของ Vivek และ Maloric อ้างถึงบรรทัดที่มี 380 ms และ 790 ms
Skippy le Grand Gourou

43
var str = "The      dog        has a long tail,      and it is RED!";
str = str.replace(/ {2,}/g,' ');

แก้ไข: หากคุณต้องการแทนที่อักขระช่องว่างทุกชนิดวิธีที่มีประสิทธิภาพที่สุดจะเป็นเช่นนั้น:

str = str.replace(/\s{2,}/g,' ');

ตลกที่ข้อความทดสอบของคุณไม่มีช่องว่างสองช่อง
Josh Stodola

รู้เพียงคุณมีสิ่งที่ฉันเพิ่งขึ้นมาด้วย +1 :)
Meder omuraliev

2
ด้วยเหตุผลบางอย่างสิ่งนี้ไม่ทำงาน ... "& nbsp;" จำนวนมาก มีการแสดงขึ้น ... น่าจะเป็นเพราะ CKEDITOR ...
AnApprentice

K เปลี่ยนข้อความของ JQUERY () ทำให้สิ่งต่าง ๆ สับสน คงที่ - ขอบคุณทุกคน!
AnApprentice

16

นี่เป็นทางออกเดียวแม้ว่าจะกำหนดเป้าหมายไปที่อักขระช่องว่างทั้งหมด :

"The      dog        has a long tail,      and it is RED!".replace(/\s\s+/g, ' ')

"The dog has a long tail, and it is RED!"

แก้ไข : สิ่งนี้น่าจะดีกว่าเนื่องจากเป็นพื้นที่เป้าหมายตามด้วยพื้นที่ 1 หรือมากกว่า:

"The      dog        has a long tail,      and it is RED!".replace(/  +/g, ' ')

"The dog has a long tail, and it is RED!"

ทางเลือกวิธีการ:

"The      dog        has a long tail,      and it is RED!".replace(/ {2,}/g, ' ')
"The dog has a long tail, and it is RED!"

ฉันไม่ได้ใช้/\s+/ด้วยตัวเองตั้งแต่นั้นมาแทนที่ช่องว่างที่มีความยาว 1 ตัวอักษรหลายครั้งและอาจมีประสิทธิภาพน้อยลงเนื่องจากมีเป้าหมายมากกว่าที่จำเป็น

ฉันไม่ได้ทดสอบสิ่งเหล่านี้อย่างจริงจังดังนั้นถ้าฉันมีข้อบกพร่อง

นอกจากนี้หากคุณกำลังจะทำการเปลี่ยนสตริงอย่าลืมกำหนดตัวแปร / คุณสมบัติให้กับการแทนที่ของตัวเองอีกครั้งเช่น:

var string = 'foo'
string = string.replace('foo', '')

ใช้ jQuery.prototype.text:

var el = $('span:eq(0)');
el.text( el.text().replace(/\d+/, '') )

1
คนแรกไม่มีจุดหมายทั้งหมด \ s \ s + หมายถึง, \ s ตามด้วยหนึ่งหรือมากกว่า \ s + ซึ่งสามารถลดลงเป็น \ s + เดียวตัวอย่างที่สองมีความแม่นยำมากขึ้นเพราะเราต้องการแทนที่ช่องว่างสองครั้งไม่ใช่ ขึ้นบรรทัดใหม่ตัวที่สามถูกปรับให้เหมาะสมยิ่งขึ้นเพราะมันใช้ได้กับตัวอย่างที่มีช่องว่าง 2+ แต่ str.replace (/ + (? =) / g, ''); ใช้กับตัวอย่างที่มีช่องว่าง 2+ เท่านั้น แต่จะบันทึกทับช่องว่างด้วยขั้นตอนช่องว่าง
Evan Carroll

4
EvanCarroll คุณล้มเหลวเนื่องจาก \ s \ s + แตกต่างจาก \ s + \ s \ s + จะตรงกับ '\ t \ t' หรือ '\ t \ t \ t' แต่ไม่ใช่ '\ t' และนั่นคือทั้งหมดที่เกี่ยวกับคุณไม่ต้องการแทนที่อักขระช่องว่างเดี่ยว f-en ทุกตัว
watain

ฉันทำ. ใช้สำหรับการค้นหาข้อความแบบเต็ม (และการแสดงผลตัวอย่าง): ไม่มีแท็บแบบสุ่มไม่ใช่ตัวแบ่งหรือสิ่ง
T4NK3R

13

ฉันมีวิธีนี้ฉันเรียกว่าวิธี Derp สำหรับการขาดชื่อที่ดีขึ้น

while (str.indexOf("  ") !== -1) {
    str = str.replace(/  /g, " ");
}

เรียกใช้ใน JSPerf ให้ผลลัพธ์ที่น่าแปลกใจ


2
ฉันจะเขินอายราวกับนรกถ้ามันปรากฏออกมาฉันเหลวไหลกรณีทดสอบแทนที่จะเป็นเรื่องจริงเร็ว: D
Nenotlep

ให้กรณีทดสอบ ... คำตอบที่ยอดเยี่ยม!
Oytun

2
นี่ทำให้วันของฉัน :-) ตลกว่า "derping" มักจะทำงานได้ดีกว่า "ฉลาด" ทั้งหมด "การแยก Derp" ดูเหมือนจะเตะตูดของมันแล้ว ยังคงสมควรได้รับการ upvoting
Fred Gandt

13

วิธีการที่แข็งแกร่งมากขึ้น: นี่ดูแลยังเอาพื้นที่เริ่มต้นและต่อท้ายถ้าพวกเขามีอยู่ เช่น:

// NOTE the possible initial and trailing spaces
var str = "  The dog      has a long   tail, and it     is RED!  "

str = str.replace(/^\s+|\s+$|\s+(?=\s)/g, "");

// str -> "The dog has a long tail, and it is RED !"

ตัวอย่างของคุณไม่มีช่องว่างเหล่านั้น แต่พวกเขาก็เป็นสถานการณ์ทั่วไปเช่นกันและคำตอบที่ได้รับการยอมรับนั้นจะตัดส่วนเหล่านั้นออกเป็นช่องว่างเดียวเช่น: "The ... RED!" ซึ่งไม่ใช่สิ่งที่คุณต้องการโดยทั่วไป


3
ฉันใช้รูปแบบนี้กับ PHP และใช้งานได้ $ parts = preg_split ("/ ^ \ s + | \ s + $ | \ s + (? = \ s) /", "Avenida Tancredo Neves, 745 Piso Térreo Sala");
Bruno Ribeiro

11

แข็งแกร่งยิ่งขึ้น:

ฟังก์ชั่นการตัดแต่ง (คำ)
{
    word = word.replace (/ [^ \ x21- \ x7E] + / g, ''); // เปลี่ยนตัวอักษรที่ไม่ใช่การพิมพ์เป็นช่องว่าง
    return word.replace (/ ^ \ s + | \ s + $ / g, ''); // ลบช่องว่างนำหน้า / ต่อท้าย
}

8

ฉันแนะนำ

string = string.replace(/ +/g," ");

เพียงช่องว่าง
หรือ

string = string.replace(/(\s)+/g,"$1");

สำหรับการเปลี่ยนผลตอบแทนหลายรายการให้เป็นผลตอบแทนเดียว


6

ฉันรู้ว่าฉันมางานปาร์ตี้สาย แต่ฉันค้นพบวิธีแก้ปัญหาที่ดี

นี่มันคือ:

var myStr = myStr.replace(/[ ][ ]*/g, ' ');

6

นี่คือทางเลือกอื่นหากคุณไม่ต้องการใช้แทนที่ (แทนที่ช่องว่างในสตริงโดยไม่ต้องใช้แทนที่จาวาสคริปต์)

var str="The dog      has a long   tail, and it     is RED!";
var rule=/\s{1,}/g;
str = str.split(rule).join(" "); 
document.write(str);

5

คำตอบที่ไม่ได้เข้ารหัสที่ครอบคลุมสำหรับมือใหม่และคณะ

นี่สำหรับหุ่นทั้งหมดเช่นฉันที่ทดสอบสคริปต์ที่เขียนโดยพวกคุณบางคนที่ไม่ได้ทำงาน

ตัวอย่าง 3 ตัวอย่างต่อไปนี้เป็นขั้นตอนที่ฉันใช้เพื่อลบอักขระพิเศษและช่องว่างเพิ่มเติมในเว็บไซต์ 3 เว็บไซต์ต่อไปนี้ (ซึ่งทั้งหมดทำงานได้อย่างสมบูรณ์) {1 EtaVisa.com 2. EtaStatus.com 3. Tikun.com} ดังนั้นฉันจึงรู้ว่าสิ่งเหล่านี้ทำงานได้อย่างสมบูรณ์แบบ

เราได้ล่ามโซ่สิ่งเหล่านี้พร้อมกันมากกว่า 50 ครั้งและไม่มีปัญหา

// นี่เป็นการลบอักขระพิเศษ + 0-9 และอนุญาตให้ใช้เฉพาะตัวอักษร (ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก)

function NoDoublesPls1()
{
var str=document.getElementById("NoDoubles1");
var regex=/[^a-z]/gi;
str.value=str.value.replace(regex ,"");
}

// นี่เป็นการลบอักขระพิเศษและอนุญาตให้ใช้ตัวอักษร (ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก) และช่องว่าง 0-9 และ

function NoDoublesPls2()
{
var str=document.getElementById("NoDoubles2");
var regex=/[^a-z 0-9]/gi;
str.value=str.value.replace(regex ,"");
}

// นี่เป็นการลบอักขระพิเศษและอนุญาตให้มีเพียงตัวอักษร (ตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก) และ 0-9 และช่องว่าง //. แทนที่ (/ \ s \ s + / g, "") ในตอนท้ายจะลบช่องว่างมากเกินไป // เมื่อฉัน ใช้เครื่องหมายคำพูดเดี่ยวมันไม่ทำงาน

function NoDoublesPls3()
{    var str=document.getElementById("NoDoubles3");
var regex=/[^a-z 0-9]/gi;
str.value=str.value.replace(regex ,"") .replace(/\s\s+/g, " ");
}

:: NEXT :: บันทึก # 3 เป็นa .js// ฉันเรียกฉันว่า NoDoubles.js

:: NEXT :: รวม JS ของคุณไว้ในหน้าของคุณ

 <script language="JavaScript" src="js/NoDoubles.js"></script>

รวมสิ่งนี้ลงในช่องแบบฟอร์ม :: เช่น

<INPUT type="text" name="Name"
     onKeyUp="NoDoublesPls3()" onKeyDown="NoDoublesPls3()" id="NoDoubles3"/>

เพื่อให้ดูเหมือนว่านี้

<INPUT type="text" name="Name" onKeyUp="NoDoublesPls3()" onKeyDown="NoDoublesPls3()" id="NoDoubles3"/>

สิ่งนี้จะลบอักขระพิเศษอนุญาตสำหรับเว้นวรรคเดียวและลบช่องว่างเพิ่มเติม


เกิดขึ้นที่นี่คืออะไร? การจัดรูปแบบดูเสียมาก
Nenotlep


1
var string = "The dog      has a long   tail, and it     is RED!";
var replaced = string.replace(/ +/g, " ");

หรือถ้าคุณต้องการแทนที่แท็บด้วย:

var replaced = string.replace(/\s+/g, " ");

1
ใช้ + ดูเหมือนจะสะอาดกว่า แต่มันจะแทนที่ช่องว่างเดียวด้วยช่องว่างเดียวซ้ำซ้อนเล็กน้อยและฉันไม่แน่ใจ แต่มันอาจสร้างปัญหาเกี่ยวกับ performace ด้วยข้อความที่ยาวกว่ามาก
ahmetunal

ฉันมักจะใช้วิธีแก้ปัญหาที่สั้นที่สุดและง่ายที่สุดที่จะทำงานได้และกังวลเฉพาะเรื่องการปรับให้เหมาะสมเท่านั้นหากฉันรู้ว่าฉันต้องจับคู่กับสตริงที่มีขนาดใหญ่มาก ณ จุดนั้นฉันจะวัดโซลูชันที่แตกต่างกันเพื่อดูว่า จะเร็วขึ้น เป็นการยากที่จะคาดการณ์ล่วงหน้าว่าอะไรจะเร็วที่สุดโดยไม่ต้องทดสอบ ตัวอย่างเช่นในล่าม JavaScript นิพจน์ทั่วไปที่ซับซ้อนบางอย่างจะทำให้คุณเปลี่ยนจากการใช้ JIT ที่คอมไพล์อย่างรวดเร็วเป็นการตีความที่ช้า
Brian Campbell

1

Jquery มีฟังก์ชัน trim () ซึ่งโดยทั่วไปจะเปลี่ยนบางสิ่งเช่น "FOo Bar" เป็น "FOo Bar"

var string = "  My     String with  Multiple lines    ";
string.trim(); // output "My String with Multiple lines"

มันมีประโยชน์มากกว่าเพราะมันลบช่องว่างที่จุดเริ่มต้นและจุดสิ้นสุดของสตริงโดยอัตโนมัติ ไม่จำเป็นต้องใช้ regex


3
ตามที่คุณพูด trim () จะลบช่องว่างที่จุดเริ่มต้นและตอนท้ายของสตริง แต่ไม่อยู่ตรงกลางของสตริงดังนั้นจะไม่ทำงานในกรณีนี้ผลลัพธ์จะเป็น "My String with Multiple บรรทัด" api.jquery.com/jQuery.trim
egvaldes



0

เราสามารถใช้ regex ต่อไปนี้อธิบายด้วยความช่วยเหลือของคำสั่งระบบ sed regex ที่คล้ายกันสามารถใช้ในภาษาและแพลตฟอร์มอื่น ๆ

เพิ่มข้อความลงในไฟล์ทดสอบการพูด

manjeet-laptop:Desktop manjeet$ cat test
"The dog      has a long   tail, and it     is RED!"

เราสามารถใช้ regex ต่อไปนี้เพื่อแทนที่ white space ทั้งหมดด้วย single space

manjeet-laptop:Desktop manjeet$ sed 's/ \{1,\}/ /g' test
"The dog has a long tail, and it is RED!"

หวังว่านี่จะทำหน้าที่ได้ตามวัตถุประสงค์


0

ลองใช้วิธีนี้เพื่อแทนที่ช่องว่างหลายช่องด้วยช่องว่างเดียว

<script type="text/javascript">
    var myStr = "The dog      has a long   tail, and it     is RED!";
    alert(myStr);  // Output 'The dog      has a long   tail, and it     is RED!'

    var newStr = myStr.replace(/  +/g, ' ');
    alert(newStr);  // Output 'The dog has a long tail, and it is RED!'
</script>

อ่านเพิ่มเติม @ การแทนที่หลายช่องว่างด้วย Single Space



0

สำหรับการควบคุมที่มากขึ้นคุณสามารถใช้การแทนที่โทรกลับเพื่อจัดการค่า

value = "tags:HUNT  tags:HUNT         tags:HUNT  tags:HUNT"
value.replace(new RegExp(`(?:\\s+)(?:tags)`, 'g'), $1 => ` ${$1.trim()}`)
//"tags:HUNT tags:HUNT tags:HUNT tags:HUNT"

0

สคริปต์นี้จะลบช่องว่างสีขาว (ช่องว่างหลายแท็บกลับ ฯลฯ ) ระหว่างคำและภายนอก:

// Trims & replaces any wihtespacing to single space between words
String.prototype.clearExtraSpace = function(){
  var _trimLeft  = /^\s+/,
      _trimRight = /\s+$/,
      _multiple  = /\s+/g;

  return this.replace(_trimLeft, '').replace(_trimRight, '').replace(_multiple, ' ');
};


0

ฉันรู้ว่าเราต้องใช้ regex แต่ในระหว่างการสัมภาษณ์ฉันถูกขอให้ทำโดยไม่ต้องใช้ regex

@ lightlytyler ช่วยฉันด้วยวิธีการด้านล่าง

const testStr = "I   LOVE    STACKOVERFLOW   LOL";

const removeSpaces = str  => {
  const chars = str.split('');
  const nextChars = chars.reduce(
    (acc, c) => {
      if (c === ' ') {
        const lastChar = acc[acc.length - 1];
        if (lastChar === ' ') {
          return acc;
        }
      }
      return [...acc, c];
    },
    [],
  );
  const nextStr = nextChars.join('');
  return nextStr
};

console.log(removeSpaces(testStr));


พิจารณา: console.log (testStr.split ("") .filter (s => s.length) .join (""))
dpjanes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.