この3つのことをこのbashコードで説明してくれませんか?


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
}

しかし、それについてこれらの3つのことを私に説明できますか?

  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番目/../..などで

  2. sed 's/^\///'最初のをドロップする/ので、に/../..なります  ../..(これは、パラメーター展開を使用して行うことができますd=${d#/})。

  3. d=.. その状態のコンテキストでのみ意味があります:

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

    これにより、dこの時点で空の場合は、親ディレクトリに移動します。(up引数なしの場合はと同等cd ..です。)

このアプローチは、1つのステップで(ユーザーの観点から)前のディレクトリに戻る機能をcd ..保持するため、反復よりも優れcd -ています。

関数は簡略化できます:

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

これは、少なくとも1つのレベルを上に移動し、n-1レベルを追加することを前提としているため、先頭を削除し/たり、空を確認したりする必要はありません$d

Athena jotathena-jotDebian のパッケージ)の使用:

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

glenn jackmanによって提案されたバリアントに基づく)。


うん、$OLDPWD踏みにじられることを頭に浮かんだ。そして、zshでcddirstackを使用するように設定します。
-muru、

割り当てるためのいくつかの理由がある$1limitだけではなく使用して$1ループには?
Nick Matteo

1
@kundorは、デフォルトが0であることを保証します(シェル演算を参照)。${1:-1}代わりに、glennのバリアントのように使用できます。
Stephen Kitt

@kundorまた、人間の可読性。適切な名前の変数は、最初に関数の内容を理解したり、コードを理解してそれを推定したりせずに、関数の読み取りを開始したときに、最初の引数の意図する意味または目的を示します。
mtraceur 2018年

2

しかし、それについてこれらの3つのことを私に説明できますか?

  1. d = $ d / ..

    これは、VARの現在の内容を連結dして/..、バックに割り当てますd
    最終結果は、のdような文字列を繰り返すことです/../../../..

  2. sed 's / ^ ///'

    投稿したコードの/指定された文字列d(echo $ d)から先頭を削除します。
    おそらくsed 's|^/||'バックスラッシュを避けるために書かれたほうがいいでしょう。

    代替(より速く、より簡単)はを書くことd=${d#/}です。

  3. d = ..

    文字列..をvarに割り当てますd
    これは、var が空であることをテストが通知した場合に、がd少なくとも1つ を持っていることを確認する方法としてのみ意味があります。これは、sedコマンドがから1文字を削除しているためにのみ発生します。 dから文字を削除する必要がない場合は、またはは必要ありません。..if [ -z "$d" ]; thendd
    sedif


あなたの質問のコードは常に少なくとも1つのディレクトリ上に移動します。

より良い

  • local d変数が空であることを確認するには十分です。他に何も必要ありません。
    ただし、ローカルはbashやdashなどの一部のシェルでのみ機能します。具体的には、ksh(としてyashlocalコマンドはありません。よりポータブルなソリューションは次のとおりです。

    [ "$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.