ตัดรายการที่ซ้ำกันออกจากตัวแปร PATH


9

ฉันแก้ไข. bashrc ของฉันบ่อยๆ อย่างไรก็ตามเมื่อฉันมีสิ่งต่าง ๆ เช่น export PATH="~/bin:~/perl5/bin:$PATH"ในไฟล์ของฉันPATHตัวแปรสภาพแวดล้อมจะเพิ่มขึ้นทุกครั้งที่ฉันจัดหาไฟล์

ตัวอย่างเช่นครั้งแรก .bashrc มีที่มาที่ตัวแปรประกอบด้วยPATH~/bin:~/perl5/bin:/usr/bin:/bin

~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/binครั้งที่สองประกอบด้วย

~/bin:~/perl5/bin:~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/binครั้งที่สามประกอบด้วย

มีวิธีง่ายๆในการเพิ่มเฉพาะสิ่งที่ไม่ได้อยู่ในเส้นทางหรือไม่?

คำตอบ:


12

ใช้ฟังก์ชั่น pathmunge () ที่มีให้ใน distro ส่วนใหญ่/etc/profile:

pathmunge () {
if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
   if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
   else
      PATH=$1:$PATH
   fi
fi
}

แก้ไข : สำหรับzshผู้ใช้typeset -U <variable_name>จะทำรายการเส้นทางซ้ำซ้อน


ขอบคุณ! มันไม่ได้อยู่ใน/etc/profileใน Debian Lenny .bashrcดังนั้นฉันรวมไว้ในของฉัน
Christopher Bottoms

การใช้งาน: pathmunge /some/pathจะเกิดขึ้น/some/pathที่จุดเริ่มต้น$PATHและpathmunge /some/path afterจะเกิดขึ้น/some/pathในตอนท้าย$PATH
Christopher Bottoms

if ! [[ $PATH =~ (^|:)$1($|:) ]] ; thenวิธีทำความสะอาดในการทำการตรวจสอบเพื่อดูว่าไดเรกทอรีโค่นอยู่ในเส้นทางปัจจุบันในเปลือกหอยทุบตีสมัยใหม่:
Christopher Cashell

ฉันจะไม่ใช้สิ่งนี้ หากรุ่นที่ไร้เดียงสาของฉันพูดว่า PATH = / foo: $ PATH นั่นหมายความว่าฉันต้องการ / foo ที่จะชนะ pathmunge /foo beforeไม่ทำอย่างนั้น วิธีที่ดีกว่าคือการเพิ่ม / foo ที่จุดเริ่มต้นแล้วลบรายการที่ซ้ำกันในภายหลัง
Don Hatch

3

ฉันมีปัญหานี้ดังนั้นฉันจึงใช้เทคนิคต่าง ๆ ที่ระบุไว้ในคำถามStackOverflow ต่อไปนี้คือสิ่งที่ฉันใช้เพื่อลดความซ้ำซ้อนของตัวแปร PATH จริงที่ได้ตั้งค่าไว้แล้วเนื่องจากฉันไม่ต้องการแก้ไขสคริปต์พื้นฐาน

    tmppath=(${PATH// /@})
    array=(${tmppath//:/ })
    for i in "${array[@]//@/ }"
    do
        if ! [[ $PATH_NEW =~ "$i" ]]; then
            PATH_NEW="${PATH_NEW}$i:";
        fi
    done;
    PATH="${PATH_NEW%:}"
    export PATH
    unset PATH_NEW

คุณสามารถเพิ่มประสิทธิภาพได้อีกเล็กน้อย แต่ฉันมีรหัสพิเศษในต้นฉบับเพื่อแสดงสิ่งที่เกิดขึ้นเพื่อให้แน่ใจว่าการตั้งค่าตัวแปรถูกต้อง สิ่งอื่นที่ควรทราบคือฉันดำเนินการดังต่อไปนี้

  1. แทนที่อักขระ SPACE ใด ๆ ด้วยอักขระ @
  2. แยกอาร์เรย์
  3. วนรอบอาร์เรย์
  4. แทนที่อักขระ @ ใด ๆ ในสตริงองค์ประกอบด้วยช่องว่าง

นี่คือเพื่อให้แน่ใจว่าฉันสามารถจัดการไดเรกทอรีที่มีช่องว่างใน (โฮมไดเรกทอรีแซมบ้าที่มีชื่อผู้ใช้ Active Directory สามารถมีช่องว่าง!)


คำเตือน: การใช้งานนี้มีข้อบกพร่องที่สำคัญ !! มันจะลบ/binหากมีรายการอื่น ๆ เช่น/usr/binเพราะการแข่งขัน regexp แม้ว่าทั้งสองรายการจะไม่เหมือนกัน!
Sukima

นี่คือการดำเนินการทางเลือกที่แก้ไขข้อผิดพลาดนั้น: github.com/sukima/dotfiles/blob/…
Sukima

1

กำหนดเส้นทางของคุณอย่างชัดเจน


ขอบคุณ ฉันพยายามตั้งค่าพา ธ อย่างชัดเจน แต่ฉันมีไฟล์. bashrc ที่ฉันใช้ในหลายสภาพแวดล้อมดังนั้นค่าเริ่มต้นที่แน่นอนPATHจะไม่เหมือนกันเสมอไป
Christopher Bottoms

1

สตริงเดียวเท่านั้น:

for i in $(echo $PATH|tr ":" "\n"|sort|uniq);do PATH_NEW="${PATH_NEW}$i:";done;PATH="${PATH_NEW%:}"

ขอบคุณ หนึ่งกุกกักนี้จะทำให้เกิดผมก็คือว่ามันตามลำดับตัวอักษร (หรือ ASCIIbetically) $PATHจัดลำดับเนื้อหาของ ฉันชอบที่จะวางไดเรกทอรีเฉพาะจุดเริ่มต้นของ$PATH(เช่น/home/username) เพื่อให้สำเนาส่วนบุคคลของไฟล์ปฏิบัติการของฉันถูกเรียกใช้แทนที่จะเป็นค่าเริ่มต้นในตัว
Christopher Bottoms

1

ฉันนึกถึงสองวิธีที่แตกต่างกันที่คุณสามารถแก้ไขปัญหานี้ได้ สิ่งแรกคือเริ่ม. bashrc ของคุณด้วยบรรทัดที่กำหนด PATH พื้นฐานของคุณอย่างชัดเจนทุกครั้งที่คุณมามันจะถูกรีเซ็ตเป็นฐานก่อนที่จะเพิ่มไดเรกทอรีเพิ่มเติม

ตัวอย่างเช่นเพิ่ม:

# Reset the PATH to prevent duplication and to make sure that we include
# everything we want.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

อีกวิธีหนึ่งคุณสามารถตรวจสอบรายการก่อนที่จะเพิ่มลงในเส้นทาง ในการทำเช่นนั้นคุณต้องใช้สิ่งต่อไปนี้:

if ! [[ $PATH =~ '~/perl5/bin' ]]
then
    PATH="~/perl5/bin:$PATH"
fi

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

หมายเหตุ: ตัวเลือกที่สองอาจใช้งานได้ตามที่เขียนในเวอร์ชันทุบตีเท่านั้น การสนับสนุนการแสดงออกปกติไม่ใช่คุณสมบัติของ Bourne Shell (/ bin / sh) และอาจไม่มีอยู่ใน shell อื่น ๆ นอกจากนี้การใช้คำพูดอาจไม่จำเป็นหรืออาจทำให้เกิดปัญหากับ bash รุ่นใหม่ล่าสุด


ขอบคุณ ฉันพยายามตั้งค่าพา ธ อย่างชัดเจน แต่ฉันมีไฟล์. bashrc ที่ฉันใช้ในหลายสภาพแวดล้อมดังนั้นค่าเริ่มต้นที่แน่นอนPATHจะไม่เหมือนกันเสมอไป
Christopher Bottoms

คุณยังคงสามารถจัดการได้โดยการตรวจสอบในสคริปต์เพื่อดูว่าชื่อโฮสต์ในเครื่องของคุณคืออะไรจากนั้นตั้งค่าเส้นทางสัมบูรณ์ของคุณอย่างเหมาะสมสำหรับเซิร์ฟเวอร์นั้น
Christopher Cashell

แค่พิมพ์ผิด: the! ifจะหายไปใน นอกจากนี้ยังเป็นเรื่องที่น่าแปลกใจ (สำหรับฉัน) ที่จะทำให้สิ่งนี้เป็นฟังก์ชั่นที่วนซ้ำอาร์กิวเมนต์ที่คั่นด้วยช่องว่างดังนั้นคุณสามารถพูดได้ว่า: add_to_PATH ~/perl5/bin ~/.bin unix.stackexchange.com/a/4973/28760 (ฉันเดาว่าcaseคำสั่งที่ใช้มีมากขึ้น แต่คุณifชัดเจนสำหรับฉัน) แก้ไขเรื่องบังเอิญแปลก ๆ ที่คำถามนั้นยังเพิ่ม perl5!
13ren

@ 13ren: ขอบคุณสำหรับบันทึก ฉันเพิ่งรู้ว่าฉันใช้อัญประกาศเดี่ยวในเส้นกำหนดเส้นทางแทนที่จะเป็นเครื่องหมายคำพูดคู่ที่ฉันควรมี ตามที่เขียนไว้มันจะแทนที่เส้นทางที่มีอยู่ของคุณด้วยชื่อตัวแปร อ๊ะ! เห็นได้ชัดว่าเป็นรายการที่ไม่ดีสำหรับฉันสำหรับการพิมพ์ผิด; ทั้งสองได้รับการแก้ไขแล้ว
Christopher Cashell

0

นี่คือทางออกของฉัน: PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

ซับง่ายหนึ่งดีที่ไม่ทิ้งร่องรอย:

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