web-dev-qa-db-ja.com

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

.bashrcファイルにfunctionがあります。私はそれが何をしているのか知っています、それはcdでX個のディレクトリをステップアップします

ここにあります:

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
<<<>>>/$
10
  1. d=$d/..は、_d変数の現在の内容に/..を追加します。 dは空から始まり、最初の反復で/..、2番目の/../..などになります。

  2. sed 's/^\///'は最初の/を削除するため、/../..../..になります(これは、パラメータ拡張d=${d#/}を使用して実行できます)。

  3. d=..は、その条件のコンテキストでのみ意味があります。

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

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

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

関数は簡略化できます:

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

これは、少なくとも1レベル上に移動することを想定し、n-1レベルを追加するため、先頭の/を削除したり、チェックしたりする必要はありません。空の$dの場合。

Athena jot(Debianのathena-jotパッケージ)の使用:

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

gleant jackman によって提案された variant に基づいています)。

24
Stephen Kitt

しかし、これらの3つのことを私に説明してくれませんか?

  1. d = $ d/..

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

  2. sed 's/^ ///'

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

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

  3. d = ..

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


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

より良い

  • local dは、変数が空であることを確認するのに十分であり、他には何も必要ありません。
    ただし、localはbashやdashなどの一部のシェルでのみ機能します。具体的には、kshyashとして)には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 \を削除します。

2
Isaac