วิธีที่ง่ายที่สุดในการลบเครื่องหมายทับจากแต่ละพารามิเตอร์คืออะไร


98

วิธีที่ง่ายที่สุดในการลบเครื่องหมายทับจากแต่ละพารามิเตอร์ในอาร์เรย์ '$ @' เพื่อrsyncคัดลอกไดเรกทอรีตามชื่อคืออะไร

rsync -a --exclude='*~' "$@" "$dir"

มีการเปลี่ยนชื่อเรื่องเพื่อความกระจ่าง หากต้องการทำความเข้าใจความคิดเห็นและคำตอบเกี่ยวกับเครื่องหมายทับหลายตัวให้ดูประวัติการแก้ไข


2
อาจซ้ำกันได้ของRemove slash จากท้ายตัวแปร
Warren Dew

คำตอบ:


160

คุณสามารถใช้${parameter%word}การขยายตัวที่เป็นรายละเอียดที่นี่ นี่คือสคริปต์ทดสอบง่ายๆที่แสดงให้เห็นถึงพฤติกรรม:

#!/bin/bash

# Call this as:
#   ./test.sh one/ two/ three/ 
#
# Output:
#  one two three

echo ${@%/}

35
+1: เพื่อเป็นการอวดดีอย่างมากนั่นจะเป็นการลบสแลชเดียวไม่ใช่สแลชต่อท้ายทั้งหมด หากต้องการลบเครื่องหมายทับจำนวนเท่าใดก็ได้:shopt -s extglob; echo "${@%%+(/)}"
glenn jackman

24
คำเตือน: คุณอาจไม่ต้องการลบเครื่องหมายทับในทุกกรณี หากระบุ "/" เป็นอาร์กิวเมนต์การลบเครื่องหมายทับจะมีผล ...
Gordon Davisson

13
PROTIP: รวมtr -s /กับตัวแปร regex เพื่อลบเครื่องหมายทับซ้ำแล้วลบเครื่องหมายทับ เช่นDIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
Dave

1
จริงๆ? เมื่อแบชแจ้งให้เรียกใช้set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"และบอกฉันว่าคุณเห็นอะไร
Glenn Jackman

1
@twalberg ฉันขอขอบคุณ "protips" ที่ไม่ใช่แค่คำตอบทางเลือกสำหรับคำถามของ OP ในกระทู้ความคิดเห็น
Kyle Strand

39

คำตอบที่ยอมรับจะตัดหนึ่งเครื่องหมายทับ

วิธีหนึ่งในการตัดแต่งเครื่องหมายทับหลาย ๆ ตัวมีดังนี้:

VALUE=/looks/like/a/path///

TRIMMED=$(echo $VALUE | sed 's:/*$::')

echo $VALUE $TRIMMED

ผลลัพธ์ใด:

/looks/like/a/path/// /looks/like/a/path

1
อย่าลืมอ้างอิงตัวแปรของคุณในกรณีที่มีช่องว่าง: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
tetsujin

1
อันที่จริงไม่จำเป็นใน$()โครงสร้าง อย่างไรก็ตามมันก็ไม่เป็นอันตรายเช่นกัน :) ดังนั้นจึงเป็นแนวทางปฏิบัติที่ดีในการใช้เครื่องหมายคำพูดคู่เช่นนี้"$VALUE"ดังนั้นคุณจึงไม่ต้องตัดสินใจว่าจะใช้อัญประกาศเมื่อใดและเมื่อใด
Chris Johnson

มีวิธีใดบ้างที่จะรวมสิ่งนี้กับการจับภาพก่อนหน้านี้? ฉันต้องการตัดโปรโตคอลและ (ถ้ามี) สแลชต่อท้ายจาก URL แต่ใช้echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'ไม่ได้ (เนื่องจากกลุ่มการบันทึกตรงกับเครื่องหมายทับเช่นกันฉันเดา) ฉันสามารถทำได้ด้วยสองคำสั่ง: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'แต่สงสัยว่าจะทำได้ด้วยคำสั่งเดียวหรือไม่?
Adam

คำตอบนี้ใช้ได้ดีกว่าสำหรับฉันด้วยไฟล์อินพุตขนาดใหญ่มาก ง่าย ๆsed 's:/*$::' < in.txt > out.txtทำงานได้ในไม่กี่วินาที
MitchellK

22

สิ่งนี้ใช้ได้กับฉัน: ${VAR%%+(/)}

ตามที่อธิบายไว้ที่นี่http://wiki.bash-hackers.org/syntax/pattern

อาจต้องตั้งค่า extglob ตัวเลือกเชลล์ ฉันไม่เห็นมันเปิดใช้งานสำหรับฉัน แต่ยังใช้งานได้


2
หากต้องการสอบถามการตั้งค่า: shopt extglobไม่มีตัวเลือก
glenn jackman

นี่คือรูปแบบการขยายภาษาและคุณจะต้องextglobตั้งค่า
นี่

1
สิ่งนี้ใช้ไม่ได้กับ bash ในตัวของ Mac OS X วิธีแก้ปัญหาโดย Sean Bright ข้างต้นทำ:${VAR%/}
Alec Jacobson

13

realpathแก้ไขเส้นทางที่กำหนด นอกจากนี้ยังลบเครื่องหมายทับ ใช้-sเพื่อป้องกันซิมลิงค์ต่อไปนี้

DIR=/tmp/a///
echo $(realpath -s $DIR)
# output: /tmp/a

1
ต้องมีโหนดทั้งหมดในเส้นทางยกเว้นโหนดสุดท้ายที่มีอยู่ หากผู้ใช้ขว้างไปในเส้นทางที่ไม่มีอยู่จริงrealpathจะล้มเหลว
Livy

2
@Livy realpath --canonicalize-missingทำงานได้อย่างถูกต้องกับส่วนใด ๆ ที่ไม่มีอยู่ของเส้นทาง
maoizm

และ realpath หายไปในบางแพลตฟอร์ม :-(
Mark Ribau

8

FYI ฉันเพิ่มฟังก์ชันทั้งสองนี้ให้.bash_profileกับคำตอบที่พบใน SO ดังที่คริสจอห์นสันกล่าวคำตอบทั้งหมดโดยใช้${x%/}เครื่องหมายทับเพียงตัวเดียวฟังก์ชันเหล่านี้จะทำตามที่พูดหวังว่าจะเป็นประโยชน์

rem_trailing_slash() {
    echo "$1" | sed 's/\/*$//g'
}

force_trailing_slash() {
    echo "$(rem_trailing_slash "$1")/"
}

4

ในzshคุณสามารถใช้:aตัวปรับแต่ง

export DIRECTORY='/some//path/name//'

echo "${DIRECTORY:a}"

=> /some/path/name

สิ่งนี้ทำหน้าที่เหมือนrealpathแต่ไม่ล้มเหลวโดยไม่มีไฟล์ / ไดเรกทอรีเป็นอาร์กิวเมนต์

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