วิธีการตัดแต่งไฟล์นามสกุลจากสตริงใน JavaScript?


295

ตัวอย่างเช่นสมมติว่าx = filename.jpgฉันต้องการได้รับfilenameซึ่งfilenameอาจเป็นชื่อไฟล์ใด ๆ (สมมติว่าชื่อไฟล์มีเพียง [a-zA-Z0-9-_] เพื่อทำให้ง่ายขึ้น)

ผมเห็นx.substring(0, x.indexOf('.jpg'))ในDZone เกร็ดเล็กเกร็ดน้อยแต่จะไม่x.substring(0, x.length-4)ทำงานได้ดีขึ้น? เพราะlengthเป็นคุณสมบัติและไม่ทำการตรวจสอบตัวละครในขณะที่indexOf()ฟังก์ชั่นและทำการตรวจสอบตัวละคร



สวยมากเช่นเดียวกับstackoverflow.com/questions/1991608/... และถ้าคุณไม่ทำสิ่งเหล่านี้มากความกังวลเกี่ยวกับประสิทธิภาพคือการเพิ่มประสิทธิภาพก่อนกำหนด
เทพพอล

ในยุคของ ES6 ให้ดูที่โมดูลPath - ในกรณีที่คุณใช้ nodejs หรือการส่งสัญญาณที่เหมาะสม
Frank Nocke

คำตอบ:


173

หากคุณทราบความยาวของส่วนขยายคุณสามารถใช้x.slice(0, -4)(โดยที่ 4 คือสามอักขระของส่วนขยายและจุด)

หากคุณไม่ทราบความยาว @John Hartsock regex จะเป็นวิธีที่เหมาะสม

หากคุณไม่ต้องการใช้นิพจน์ทั่วไปคุณสามารถลองทำสิ่งนี้ (ลดประสิทธิภาพ):

filename.split('.').slice(0, -1).join('.')

โปรดทราบว่ามันจะล้มเหลวในไฟล์ที่ไม่มีนามสกุล


ฉันชอบวิธีนี้ดีที่สุด .jpgมันสะอาดและฉันสามารถใช้มันทำให้ฉันรู้ว่านามสกุลไฟล์อยู่เสมอ ฉันกำลังมองหาบางอย่างเช่นรูบี้x[0..-5]และx.slice(0, -4)ดูดีมาก! ขอบคุณ! และขอขอบคุณทุกคนสำหรับทุกทางเลือกที่แข็งแกร่งอื่น ๆ ที่มีให้!
ma11hew28

22
นี่ไม่ใช่ทางออกที่ดีที่สุดโปรดตรวจสอบวิธีแก้ไขปัญหาอื่น ๆ ด้านล่าง
bunjeeb

8
และถ้าคุณไม่แน่ใจ 100% เกี่ยวกับความยาวของนามสกุลอย่าทำอย่างนี้: "picture.jpeg".slice(0, -4)-> "รูปภาพ"
พื้นฐาน

13
นี่เป็นวิธีที่อันตรายเพราะคุณไม่ทราบความยาวของรูปแบบ
Coder

"ถ้าคุณทราบความยาวของการขยาย" มันเป็นเวลาหลายสิบปีแล้วที่นี่เป็นข้อสันนิษฐานที่ยอมรับได้ อย่าใช้สิ่งนี้อีกต่อไป
Alexander - Reinstate Monica

454

ไม่แน่ใจว่าสิ่งใดจะทำงานได้เร็วขึ้น แต่สิ่งนี้น่าเชื่อถือมากขึ้นเมื่อพูดถึงส่วนขยายที่ชอบ.jpegหรือ.html

x.replace(/\.[^/.]+$/, "")

15
คุณอาจต้องการที่จะไม่อนุญาต / เป็นตัวแยกเส้นทางดังนั้น regexp จึงเป็น /\.ه^/. เหมือนกัน +$/
gsnedders

สิ่งนี้ใช้ได้กับความยาวของนามสกุลไฟล์ (.txt หรือ. html หรือ. htaccess) และอนุญาตให้ชื่อไฟล์มีอักขระระยะเวลา (.) เพิ่มเติม มันจะไม่จัดการเช่น. tar.gz เนื่องจากส่วนขยายของตัวเองมีจุด เป็นเรื่องปกติมากขึ้นที่ชื่อไฟล์จะมีช่วงเวลาเพิ่มเติมมากกว่านามสกุลไฟล์ ขอบคุณ!
Steve Seeger

2
@Vik มีความแตกต่างระหว่าง 'คำตอบที่ถูกต้อง' และคำตอบที่ยอมรับได้ คำตอบที่ได้รับการยอมรับเป็นเพียงคำตอบที่เป็นประโยชน์สำหรับผู้ที่ถามคำถาม
Steven

4
ฉันคิดว่าอาจมีปัญหากับแพลตฟอร์ม Windows เนื่องจากอาจมีเครื่องหมายทับด้านหลัง ดังนั้น regexp ควรจะเป็น
Alex Chuev

1
@ElgsQianChen นี่เป็นเครื่องมือที่ดีสำหรับคุณที่จะตอบคำถามของคุณช่วยเหลือregexr.com
จอห์น Hartsock

281

ในnode.jsชื่อของไฟล์ที่ไม่มีนามสกุลสามารถรับได้ดังต่อไปนี้

const path = require('path');
const filename = 'hello.html';

path.parse(filename).name; // hello
path.parse(filename).ext;  // .html

คำอธิบายเพิ่มเติมที่หน้าเอกสารของNode.js


2
สิ่งที่คุณกำลังพูดถึง @kaasdude .... วิธีนี้จะลบส่วนขยายบนโหนดได้อย่างมีประสิทธิภาพไม่แน่ใจว่าสิ่งที่คุณต้องการที่จะแสดง แต่วิธีนี้ใช้งานได้ไข่มุก
Erick

1
คำตอบนี้ค่อนข้าง จำกัด เฉพาะโหนดฝั่งเซิร์ฟเวอร์ หากคุณพยายามใช้สิ่งนี้ในรหัสการตอบสนองดูเหมือนว่าจะไม่นำเข้า
ชาร์ลี

1
หากคุณต้องการลบส่วนขยายออกจากเส้นทางที่มีไดเรกทอรีคุณสามารถทำvar parsed = path.parse(filename)ตามpath.join(parsed.dir, parsed.name)ได้
Jespertheend

let base = path.basename( file_path, path.extname( file_path ) )เป็นไปได้ก็คือ
bicarlsen

116

x.length-4เฉพาะบัญชีสำหรับนามสกุล 3 ตัว เกิดอะไรขึ้นถ้าคุณมีfilename.jpegหรือfilename.pl?

แก้ไข:

คำตอบ ... แน่ใจว่าถ้าคุณมักจะมีส่วนขยายของ.jpg, x.length-4จะทำงานได้ดี

อย่างไรก็ตามหากคุณไม่ทราบความยาวของส่วนขยายโซลูชันใด ๆ จำนวนหนึ่งจะดีกว่า / แข็งแกร่งกว่า

x = x.replace(/\..+$/, '');

หรือ

x = x.substring(0, x.lastIndexOf('.'));

หรือ

x = x.replace(/(.*)\.(.*?)$/, "$1");

หรือ (ด้วยชื่อไฟล์สมมติฐานมีเพียงหนึ่งจุด)

parts = x.match(/[^\.]+/);
x = parts[0];

หรือ (มีจุดเดียวเท่านั้น)

parts = x.split(".");
x = parts[0];

12
?? คุณสามารถมีชื่อไฟล์เช่น: "summer.family.jpg" ในกรณีแยก ('.') [0]จะส่งกลับเฉพาะชื่อไฟล์บางส่วนเท่านั้น ฉันจะลบอันนั้นออกจากคำตอบหรือระบุอย่างชัดเจนภายใต้ปัญหาสำหรับตัวอย่างนั้น @basarat ...
Roko C. Buljan

บางสิ่งที่ฉันทำบ่อยๆเกี่ยวกับการแยกส่วน:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
เรดิแกนและ

x.split (".") ไม่ควรได้รับการพิจารณาคำตอบด้วยซ้ำ ฉันรู้ว่าฉันใช้ '.' ในอนุสัญญาการตั้งชื่อไฟล์เกือบทั้งหมดของฉันเช่น 'survey.controller.js' หรือ 'my.family.jpg'
Lee Brindley

@ Lee2808: ดังนั้นการเตือนเพียงหนึ่งจุด นี่เป็นเพียงการแสดงให้เห็นว่ามีหลายวิธีขึ้นอยู่กับแอปพลิเคชัน แน่นอนฉันจะใช้วิธีอื่นอย่างใดอย่างหนึ่งในเกือบทุกกรณี
Jeff B

x = x.substr(0, x.lastIndexOf('.'));- คุณอาจหมายถึงx = x.substring(0, x.lastIndexOf('.'));อะไร
Dziad Borowy

39

คุณอาจใช้สมมุติฐานที่ว่าจุดสุดท้ายจะเป็นตัวคั่นส่วนขยาย

var x = 'filename.jpg';
var f = x.substr(0, x.lastIndexOf('.'));

หากไฟล์ไม่มีนามสกุลไฟล์จะคืนค่าสตริงว่าง เพื่อแก้ไขว่าใช้ฟังก์ชั่นนี้

function removeExtension(filename){
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);
}

คำเตือนสิ่งนี้จะล้มเหลวหากไม่มีนามสกุลไฟล์ คุณเหลือสตริงว่าง
แบรด

18
เวอร์ชันที่สั้นลงที่ไม่มีจุด var f = x.substr(0, x.lastIndexOf('.')) || x;สิ่งนี้ใช้ได้เพราะสตริงว่างเปล่าเป็นเท็จดังนั้นมันจึงส่งกลับค่า x
Jonathan Rowny

22

ฉันชอบอันนี้เพราะมันเป็นหนึ่งซับที่ไม่ยากเกินไปที่จะอ่าน:

filename.substring(0, filename.lastIndexOf('.')) || filename


12

ใช้งานได้แม้ว่าตัวคั่นจะไม่ปรากฏในสตริง

String.prototype.beforeLastIndex = function (delimiter) {
    return this.split(delimiter).slice(0,-1).join(delimiter) || this + ""
}

"image".beforeLastIndex(".") // "image"
"image.jpeg".beforeLastIndex(".") // "image"
"image.second.jpeg".beforeLastIndex(".") // "image.second"
"image.second.third.jpeg".beforeLastIndex(".") // "image.second.third"

ยังสามารถใช้เป็นซับในแบบนี้:

var filename = "this.is.a.filename.txt";
console.log(filename.split(".").slice(0,-1).join(".") || filename + "");

แก้ไข: นี่คือทางออกที่มีประสิทธิภาพมากขึ้น:

String.prototype.beforeLastIndex = function (delimiter) {
    return this.substr(0,this.lastIndexOf(delimiter)) || this + ""
}

10

ฉันไม่รู้ว่ามันเป็นตัวเลือกที่ถูกต้องหรือไม่ แต่ฉันใช้สิ่งนี้:

name = filename.split(".");
// trimming with pop()
name.pop();
// getting the name with join()
name.join('.'); // we split by '.' and we join by '.' to restore other eventual points.

มันไม่ใช่แค่การผ่าตัดที่ฉันรู้ แต่อย่างน้อยมันควรจะใช้ได้เสมอ!

อัปเดต: หากคุณต้องการผู้ให้บริการรายวันคุณอยู่ที่นี่:

(name.split('.').slice(0, -1)).join('.')


1
ไม่ควรเป็น name.join ('') แต่เป็น name.join ('.') คุณแยกโดยจุด แต่เข้าร่วมด้วยเครื่องหมายจุลภาคดังนั้นhello.name.txtส่งคืนhello, name
Evil




6

คำตอบที่ยอมรับจะแยกส่วนขยายสุดท้ายเท่านั้น ( .jpeg) ซึ่งอาจเป็นตัวเลือกที่ดีในกรณีส่วนใหญ่

ฉันเคยต้องดึงส่วนขยายทั้งหมด ( .tar.gz) และชื่อไฟล์ถูก จำกัด ไม่ให้มีจุด (ดังนั้น2015-01-01.backup.tarจะไม่เป็นปัญหา):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");

4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"

นี่เป็นวิธีเดียวที่ใช้ได้สำหรับเส้นทางแบบเต็ม: path/name.ext-> paht/nameแทนที่จะเพิ่งกลับมาnameแต่ฉันอยากจะทำกับfs.parseมันมากกว่านี้: stackoverflow.com/a/59576950/895245
Ciro Santilli 郝海东冠状病六四事件法轮功

3

หากคุณต้องประมวลผลตัวแปรที่มีเส้นทางที่สมบูรณ์ (เช่น:) thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg"และคุณต้องการกลับมาเพียง "ชื่อไฟล์" คุณสามารถใช้:

theName = thePath.split("/").slice(-1).join().split(".").shift();

ผลลัพธ์จะเป็นtheName == "filename" ;

หากต้องการลองเขียนคำสั่งต่อไปนี้ลงในหน้าต่างคอนโซลของตัวแก้ไขข้อบกพร่อง chrome: window.location.pathname.split("/").slice(-1).join().split(".").shift()

หากคุณมีการดำเนินการเพียงแค่ชื่อไฟล์และนามสกุล (อดีต .: theNameWithExt = "filename.jpg"):

theName = theNameWithExt.split(".").shift();

ผลลัพธ์จะเป็นtheName == "filename"เหมือนกับข้างบน

หมายเหตุ:

  1. สาเหตุแรกช้ากว่าเล็กน้อยทำให้ทำงานได้มากกว่า แต่ทำงานได้ทั้งสองกรณีกล่าวคือสามารถแยกชื่อไฟล์โดยไม่มีนามสกุลจากสตริงที่กำหนดซึ่งมีพา ธ หรือชื่อไฟล์ด้วย ex ในขณะที่ตัวที่สองทำงานได้ก็ต่อเมื่อตัวแปรที่กำหนดมีชื่อไฟล์ที่มีนามสกุลเช่น filename.ext แต่จะเร็วกว่าเล็กน้อย
  2. โซลูชั่นทั้งสองทำงานได้ทั้งไฟล์โลคอลและเซิร์ฟเวอร์

แต่ฉันไม่สามารถพูดอะไรได้เลยเกี่ยวกับการเปรียบเทียบกับคำตอบอื่น ๆ หรือสำหรับเบราว์เซอร์หรือระบบปฏิบัติการที่เข้ากันไม่ได้

ตัวอย่างการทำงาน 1: เส้นทางที่สมบูรณ์

var thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg";
theName = thePath.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

ตัวอย่างการทำงาน 2: ชื่อไฟล์ที่มีนามสกุล

var theNameWithExt = "filename.jpg";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

ตัวอย่างการทำงาน 2: ชื่อไฟล์ที่มีนามสกุลเป็นสองเท่า

var theNameWithExt = "filename.tar.gz";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  


3

แม้ว่ามันจะค่อนข้างช้า แต่ฉันจะเพิ่มวิธีการอื่นในการรับชื่อไฟล์โดยไม่ต้องใช้นามสกุลเก่าโดยใช้ JS- ธรรมดา

path.replace(path.substr(path.lastIndexOf('.')), '')


หรือpath.split('.').pop()นามสกุลไฟล์ส่วนหนึ่ง
mixdev

ที่จริงแล้วเขาพยายามรับชื่อไฟล์ไม่ใช่นามสกุล!
Munim Dibosh

3

Node.js ลบส่วนขยายออกจากไดเรกทอรีการเก็บเส้นทางแบบเต็ม

https://stackoverflow.com/a/31615711/895245ตัวอย่างเช่นทำpath/hello.html-> helloแต่ถ้าคุณต้องการpath/hello.html-> path/helloคุณสามารถใช้สิ่งนี้:

#!/usr/bin/env node
const path = require('path');
const filename = 'path/hello.html';
const filename_parsed = path.parse(filename);
console.log(path.join(filename_parsed.dir, filename_parsed.name));

ไดเรกทอรีผลลัพธ์เช่นกัน:

path/hello

https://stackoverflow.com/a/36099196/895245ก็ประสบความสำเร็จเช่นกัน แต่ฉันพบว่าวิธีการนี้น่าพอใจยิ่งขึ้น

ทดสอบใน Node.js v10.15.2


0

นี่คือที่การแสดงออกปกติมามีประโยชน์! .replace()วิธีการของ Javascript จะแสดงออกอย่างสม่ำเสมอและคุณสามารถใช้สิ่งนั้นเพื่อบรรลุสิ่งที่คุณต้องการ:

// assuming var x = filename.jpg or some extension
x = x.replace(/(.*)\.[^.]+$/, "$1");

0

อีกหนึ่งสายการบิน - เราถือว่าไฟล์ของเราเป็นรูปภาพ jpg >> ex: var yourStr = 'test.jpg';

    yourStr = yourStr.slice(0, -4); // 'test'

0

คุณสามารถใช้pathในการซ้อมรบ

var MYPATH = '/User/HELLO/WORLD/FILENAME.js';
var MYEXT = '.js';
var fileName = path.basename(MYPATH, MYEXT);
var filePath = path.dirname(MYPATH) + '/' + fileName;

เอาท์พุต

> filePath
'/User/HELLO/WORLD/FILENAME'
> fileName
'FILENAME'
> MYPATH
'/User/HELLO/WORLD/FILENAME.js'


0

นี่คือรหัสที่ฉันใช้เพื่อลบส่วนขยายจากชื่อไฟล์โดยไม่ต้องใช้ regex หรือ indexOf (ไม่รองรับ indexOf ใน IE8) จะถือว่าส่วนขยายเป็นข้อความใด ๆ หลังจากส่วนสุดท้าย '.' ตัวละคร

มันใช้งานได้สำหรับ:

  • ไฟล์ที่ไม่มีนามสกุล: "myletter"
  • ไฟล์ที่มี '.' ในชื่อ: "my.letter.txt"
  • ไม่ทราบความยาวของนามสกุลไฟล์: "my.letter.html"

นี่คือรหัส:

var filename = "my.letter.txt" // some filename

var substrings = filename.split('.'); // split the string at '.'
if (substrings.length == 1)
{
  return filename; // there was no file extension, file was something like 'myfile'
}
else
{
  var ext = substrings.pop(); // remove the last element
  var name = substrings.join(""); // rejoin the remaining elements without separator
  name = ([name, ext]).join("."); // readd the extension
  return name;
}

ล้มเหลวด้วยการส่งออกเป็นhello.tar.gz hellotar
Asif Ali

#AsifAli ขอบคุณคุณถูกต้องฉันลืมอ่านไฟล์นามสกุล ฉันได้อัปเดตคำตอบแล้วฉันหวังว่าจะใช้งานได้ในขณะนี้
สมองน้อย

-3

ฉันจะใช้บางอย่างเช่น x.substring (0, x.lastIndexOf ('.')) หากคุณต้องการประสิทธิภาพอย่าไปใช้จาวาสคริปต์เลย :-p ไม่ข้อความสั่งอีกหนึ่งข้อความไม่สำคัญสำหรับ 99.99999% ของวัตถุประสงค์ทั้งหมด


2
"หากคุณต้องการประสิทธิภาพอย่าไปใช้จาวาสคริปต์เลย" - คุณแนะนำอะไรให้ใช้ในเว็บแอปพลิเคชั่น .. ?
TJ

เขาไม่ได้พูดถึงการใช้งานเว็บ
Lucas Moeskops

1
คำถามนี้ถูกถามและตอบถูกโพสต์ในปี 2010 เมื่อ 7 ปีที่แล้วและ JavaScript นั้นถูกใช้อย่างแพร่หลายในเว็บแอปพลิเคชั่นเท่านั้น (โหนดเพิ่งเกิดมามันไม่ได้มีมัคคุเทศก์หรือ NPM ในเวลานั้น)
TJ

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