วิธีรับส่วนสุดท้ายของลิงค์ http ใน Bash


25

ฉันมีลิงค์ http:

http://www.test.com/abc/def/efg/file.jar 

และฉันต้องการบันทึกส่วนสุดท้าย file.jar เป็นตัวแปรดังนั้นสตริงเอาต์พุตคือ "file.jar"

เงื่อนไข : ลิงค์มีความยาวต่างกันเช่น:

http://www.test.com/abc/def/file.jar.

ฉันลองแบบนั้น:

awk -F'/' '{print $7}'

แต่ปัญหาคือความยาวของ URL ดังนั้นฉันต้องการคำสั่งที่สามารถใช้สำหรับความยาว URL ใด ๆ

คำตอบ:


51

ใช้awkสำหรับสิ่งนี้จะได้ผล แต่มันเป็นการล่ากวางด้วยปืนครก หากคุณมี URL ของคุณอยู่แล้วมันค่อนข้างง่ายที่จะทำสิ่งที่คุณต้องการหากคุณใส่ลงในตัวแปรเชลล์และใช้การbashทดแทนพารามิเตอร์ในตัว:

$ myurl='http://www.example.com/long/path/to/example/file.ext'
$ echo ${myurl##*/}
file.ext

วิธีการทำงานนี้คือการลบคำนำหน้าที่ตรงกับความตะกละ '/ /' ซึ่งเป็นสิ่งที่##ผู้ประกอบการทำ:

${haystack##needle} # removes any matching 'needle' from the
                    # beginning of the variable 'haystack'

คำอธิบายใดที่จะไปด้วย
เครื่องหมายคำถาม

แน่ใจ มันจะทำอย่างไร
DopeGhoti

เป็นสิ่งที่ดี :)
เครื่องหมายคำถาม

2
หากคุณต้องการตัดสตริงการสืบค้นคุณสามารถกำหนดให้กับตัวแปรกลางเช่นfile=${myurl##*/}จากนั้นใช้การจับคู่แบบโลภย้อนกลับเพื่อสำรองข้อมูล?(อย่าลืมหลบหนี!) เช่นecho ${file%%\?*}
Doktor J

21

basenameและใช้dirnameงานได้ดีกับ URL เช่นกัน:

> url="http://www.test.com/abc/def/efg/file.jar"
> basename "$url"; basename -s .jar "$url"; dirname "$url"
file.jar
file
http://www.test.com/abc/def/efg

+1 ยอดเยี่ยมมันใช้งานได้เพราะ URL และ PATH และทั้ง URIs
Tulains Córdova

1
@ TulainsCórdovaเส้นทางไม่ใช่URI ; สิ่งนี้ทำงานได้เพราะbasenameและdirnameแยกสตริงใน / และที่เกิดขึ้นกับ URL ด้วยอย่างน้อยก็ตราบใดที่มันไม่มีส่วนในตัวเครื่อง (ไม่ใช่ URIs โดยทั่วไป)
Stephen Kitt

ในบทความวิกิพีเดียเกี่ยวกับ URI ของพวกเขาให้ดังต่อไปนี้เป็นตัวอย่างที่ถูกต้องของการอ้างอิง URI: /relative/URI/with/absolute/path/to/resource.txt, relative/path/to/resource.txt, ../../../resource.txtและresource.txt en.wikipedia.org/wiki/...
Tulains Córdova

1
@ TulainsCórdova Wikipedia ไม่ผิด/relative/pathอาจเป็นเส้นทางของระบบไฟล์หรือ URI ที่สัมพันธ์กัน แต่อันไหนของมันก็ขึ้นอยู่กับบริบท เมื่อมันถูกใช้เป็นเส้นทางของระบบไฟล์มันไม่ใช่ URI เมื่อมันถูกใช้เป็น URI มันไม่ใช่เส้นทางของระบบไฟล์ การพูดว่ามันเป็น URI เพียงเพราะมันเกิดขึ้นเพื่อให้เข้ากับไวยากรณ์เหมือนกับว่าคำแต่ละคำในความคิดเห็นนี้เป็น URI เช่นกัน
hvd

11

ด้วยawkคุณสามารถใช้$NFเพื่อรับฟิลด์สุดท้ายโดยไม่คำนึงถึงจำนวนฟิลด์:

awk -F / '{print $NF}'

หากคุณเก็บสตริงนั้นในตัวแปรเชลล์คุณสามารถใช้:

a=http://www.test.com/abc/def/efg/file.jar
printf '%s\n' "${a##*/}"

6

คำตอบที่โพสต์ส่วนใหญ่จะไม่สมบูรณ์ใน URL ที่มีสตริงหรือเป้าหมายของแบบสอบถามเช่นตัวอย่างต่อไปนี้:

https://example.com/this/is/a/path?query#target

Python มีการแยกวิเคราะห์ URL ในไลบรารีมาตรฐาน มันง่ายกว่าที่จะปล่อยให้มันทำ เช่น,

from urllib import parse
import sys
path = parse.urlparse(sys.stdin.read().strip()).path
print("/" if not path or path == "/" else path.rsplit("/", 1)[-1])

คุณสามารถย่อให้เป็นหนึ่งเดียวpython3 -cเพื่อใช้ในเชลล์สคริปต์:

echo 'https://example.com/this/is/a/path/componets?query#target' \
    | python3 -c 'from urllib import parse; import sys; path = parse.urlparse(sys.stdin.read().strip()).path; print("/" if not path or path == "/" else path.rsplit("/", 1)[-1])'

(นอกจากนี้คุณยังสามารถแยกสคริปต์ออกเพื่อความสะดวกในการอ่านซึ่ง'จะทำให้คุณใส่บรรทัดใหม่ได้)

แน่นอนตอนนี้เชลล์สคริปต์ของคุณมีการพึ่งพา Python

(ฉันไม่แน่ใจเล็กน้อยเกี่ยวกับกรณีที่พยายามจัดการกับกรณีที่องค์ประกอบเส้นทางของ URL คือรูท ( /); ปรับ / ทดสอบว่าเกี่ยวข้องกับคุณหรือไม่)


1

วิธีหนึ่งคือไปrevยัง URL จากนั้นจึงตัดฟิลด์และrevอีกครั้ง เช่น:

echo 'http://www.test.com/abc/def/efg/file.jar ' | rev | cut -d '/' -f 1 | rev

เอาท์พุท:

file.jar 

ตัวอย่างที่ 2:

echo 'http://www.test.com/abc/cscsc/sccsc/def/efg/file.jar ' | rev | cut -d '/' -f 1 | rev

เอาท์พุท:

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