คุณสามารถอธิบายสามสิ่งนี้ในรหัสทุบตีนี้ให้ฉันได้ไหม


10

ฉันมีfunctionใน.bashrcไฟล์ของฉัน ฉันรู้ว่ามันทำอะไรมันทำตามขั้นตอน X หลาย ๆ ไดเรกทอรีด้วยcd

นี่มันคือ:

up()
{
    local d=""
    limit=$1
    for ((i=1 ; i <= limit ; i++))
      do
        d=$d/..
      done
    d=$(echo $d | sed 's/^\///')
    if [ -z "$d" ]; then
      d=..
    fi
    cd $d
}

แต่คุณสามารถอธิบายสามสิ่งนี้จากฉันได้ไหม?

  1. d=$d/..
  2. sed 's/^\///'
  3. d=..

ทำไมไม่ทำเช่นนี้:

up()
{
    limit=$1

    for ((i=1 ; i <= limit ; i++))
    do
        cd ..
    done
}

การใช้งาน:

<<<>>>~$ up 3
<<<>>>/$

คำตอบ:


24
  1. d=$d/..เพิ่ม/..เนื้อหาปัจจุบันของdตัวแปร dเริ่มว่างเปล่าจากนั้นการทำซ้ำครั้งแรกจะทำให้มัน/..ที่สอง/../..ฯลฯ

  2. sed 's/^\///'ลดลงก่อน/จึง/../..กลายเป็น  ../..(สิ่งนี้สามารถทำได้โดยใช้การขยายพารามิเตอร์d=${d#/})

  3. d=.. เพียงทำให้รู้สึกในบริบทของสภาพ:

    if [ -z "$d" ]; then
      d=..
    fi

    วิธีนี้ช่วยให้มั่นใจได้ว่าหากdไม่มีข้อมูล ณ จุดนี้คุณไปที่ไดเรกทอรีหลัก ( upโดยไม่มีข้อโต้แย้งเทียบเท่าcd ..)

วิธีนี้ดีกว่าการทำซ้ำcd ..เพราะมันรักษาcd -- ความสามารถในการกลับไปยังไดเรกทอรีก่อนหน้า (จากมุมมองของผู้ใช้) ในขั้นตอนเดียว

ฟังก์ชันนี้สามารถทำให้ง่ายขึ้น:

up() {
  local d=..
  for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
  cd $d
}

นี้จะถือว่าเราต้องการที่จะย้ายขึ้นอย่างน้อยหนึ่งระดับและเพิ่มn - 1ระดับดังนั้นเราจึงไม่จำเป็นต้องเอาชั้นนำหรือตรวจสอบที่ว่างเปล่า/$d

ใช้ Athena jot( athena-jotแพคเกจใน Debian):

up() { cd $(jot -b .. -s / "${1:-1}"); }

(ขึ้นอยู่กับตัวแปรที่แนะนำโดยเกล็นแจ็คแมน )


ใช่$OLDPWDได้รับการเหยียบย่ำอยู่ในใจ และบน zsh ด้วยcdชุดที่จะใช้ dirstack นั่นก็เช่นกัน
muru

มีเหตุผลบางอย่างในการมอบหมาย$1ให้limitแทนที่จะใช้เพียงแค่$1ในลูปหรือไม่?
Nick Matteo

1
@kundor จะทำให้มั่นใจว่าค่าเริ่มต้นคือ 0 (ดูเลขคณิตของเชลล์ ) เราสามารถใช้${1:-1}แทนได้เหมือนในตัวแปรของ Glenn
Stephen Kitt

@ kundor นอกจากนี้มนุษย์สามารถอ่านได้ ตัวแปรที่มีชื่อดีจะบอกคุณว่าความหมายหรือวัตถุประสงค์ของอาร์กิวเมนต์แรกคืออะไรเมื่อคุณเริ่มอ่านฟังก์ชั่นโดยไม่ต้องรู้ก่อนว่าฟังก์ชันทำอะไรหรือเข้าใจโค้ดเพื่อสรุปมัน
mtraceur

2

แต่คุณสามารถอธิบายสามสิ่งนี้จากฉันได้ไหม?

  1. d = $ d / ..

    นี้เชื่อมเนื้อหาปัจจุบันของ var dด้วยและกำหนดมันกลับไป/.. ผลลัพธ์ที่ได้คือการทำให้สตริงซ้ำเช่นd
    d/../../../..

  2. sed 's / ^ ///'

    ลบส่วนนำ/จากสตริงที่ให้มาd(echo $ d) ในรหัสที่คุณโพสต์
    น่าจะเขียนได้ดีกว่าsed 's|^/||'เพื่อหลีกเลี่ยงแบ็กสแลช

    ทางเลือก (เร็วขึ้นและง่าย) d=${d#/}คือการเขียน

  3. d = ..

    กำหนดสตริงเพื่อวา.. นี่เป็นเพียงวิธีการเพื่อให้แน่ใจว่ามีอย่างน้อยหนึ่งรายการในกรณีที่สัญญาณทดสอบว่า var ว่างเปล่า และนั่นสามารถเกิดขึ้นได้เพราะคำสั่ง sed กำลังลบอักขระหนึ่งตัวออกไป หากมีความจำเป็นที่จะต้องเอาตัวละครจาก d ไม่มีไม่มีความจำเป็นในการหรือd
    d ..if [ -z "$d" ]; thendd
    sedif


รหัสในคำถามของคุณจะเลื่อนขึ้นอย่างน้อยหนึ่ง dir

ดีกว่า

  • local dก็เพียงพอที่จะตรวจสอบให้แน่ใจว่าตัวแปรนั้นว่างเปล่าไม่จำเป็นต้องมีอะไรอีก
    อย่างไรก็ตามการทำงานในท้องถิ่นในเชลล์บางตัวเท่านั้นเช่น bash หรือ dash โดยเฉพาะksh(เป็นyash) ไม่มีlocalคำสั่ง โซลูชันแบบพกพาเพิ่มเติมคือ:

    [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
  • for((ไวยากรณ์ไม่ได้เป็นแบบพกพา ควรใช้สิ่งที่ดีกว่า:

    while [ "$((i+=1))" -lt "$limit" ]; do
  • แข็งแรง
    หากค่าที่กำหนดให้กับอาร์กิวเมนต์อันดับแรกของฟังก์ชันอาจเป็นค่าลบหรือข้อความฟังก์ชันควรมีความทนทานในการประมวลผลค่าเหล่านั้น
    ครั้งแรกที่ช่วยให้ จำกัด ค่าที่ตัวเลขเท่านั้น (ฉันจะใช้cสำหรับการcount):

    c=${1%%[!0-9]*}

    จากนั้น จำกัด จำนวนการนับเฉพาะกับค่าบวก:

    let "c = (c>0)?c:0"

ฟังก์ชั่นนี้จะยอมรับ 0 หรือข้อความอย่างไม่มีข้อผิดพลาด:

up()
{
    [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
    c=${1%%[!0-9]*}
    c=$(((c>0)?c:0))
    while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
    echo \
        cd "${d%/}"         # Removing the trailing / is not really needed for cd
                            # but it is nice to know it could be done cleanly.
}

up 2
up 0
up asdf

ลบecho \เมื่อคุณได้ทดสอบฟังก์ชั่น

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