10

修飾子 # ## % %% は理解できますが、tcsh のようにそれらを連結できるかどうかはわかりません。

tcsh での例

set f = /foo/bar/myfile.0076.jpg
echo $f:r:e
--> 0076

echo $f:h:t
--> bar

bash では、次のようなことを行う方法を知りたいです。

echo ${f%.*#*.}

一行で。

私の目標は、コマンド ラインで必要に応じてさまざまな方法でファイル名を操作できるようにすることです。特定のケースのスクリプトを作成しようとしているわけではありません。したがって、これらの修飾子を連鎖させる方法がある場合、または別の方法がある場合は、ぜひ知りたいです。ありがとう

4

3 に答える 3

7

bash では、パラメーター展開をネストできますが、効果的には の単語部分でのみ有効${parameter#word}です。

例えば:

$ var="foo.bar.baz"; echo ${var%.*}
foo.bar
$ var="foo.bar.baz"; echo ${var#foo.bar}
.baz
$ var="foo.bar.baz"; echo ${var#${var%.*}}
.baz

純粋なパラメーター展開で必要なことを行うには、次のような一時変数が必要です。

$ var="/foo/bar/myfile.0076.jpg"; tmp=${var#*.}; out=${tmp%.*}; echo $out
0076

ただし、ビルトインを使用する場合は、set次のように検索/置換パラメーター展開を巧妙に使用して、実際に一度にすべてのフィールドにアクセスできます。

$ var="/foo/bar/myfile.0076.jpg"; set -- ${var//[.\/]/ }; echo $4
0076
于 2011-02-28T20:32:22.697 に答える
3

達成しようとしていることができる 1 つの方法は、Bash の正規表現 (バージョン 3.2 以降) を使用することです。

f=/foo/bar/myfile.0076.jpg
pattern='/([^/]*)/[^/]*\.([0-9]*)\.'
[[ $f =~ $pattern ]]
echo ${BASH_REMATCH[1]}    # bar
echo ${BASH_REMATCH[2]}    # 0076

ブレース展開演算子を順番に適用できます。

f=/foo/bar/myfile.0076.jpg
r=${f%.*}  # remove the extension
r=${r#*.}  # remove the part before the first (now only) dot
echo $r    # 0076
r=${f%/*}  # similar, but use slash instead of dot
r=${r##*/}
echo $r    # bar

もう 1 つの方法は、ブレース展開と拡張グロブを組み合わせることです。

shopt -s extglob
f=/foo/bar/myfile.0076.jpg
r=${f/%*([^0-9])}    # remove the non-digits from the beginning
r=${r/#*([^0-9])}    # remove the non-digits from the end
echo $r              # 0076
r=${f/#*(\/*([^\/])\/)}    # remove the first two slashes and what's between them
r=${r/%\/*(?)}             # remove the last slash and everything after it
echo $r                    # bar

編集:

basenameとを実行する私の Bash 関数は次のとおりですdirname。それらは、これらのユーティリティと同様の方法でエッジ ケースを処理します。

bn ()
{
    [[ $1 == / ]] && echo / || echo "${1##*/}"
}

dn ()
{
    [[ -z ${1%/*} ]] && echo / || {
        [[ $1 == .. ]] && echo . || echo "${1%/*}"
    }
}
于 2011-03-01T01:28:01.390 に答える
1

tcsh ファイル名修飾子の単純さにかなり近い解決策を見つけました。4 つの関数を作成し、.bashrc に配置しました。

e() # the extension
E() # everything but the extension
t() # the tail - i.e. everything after the last /
T() # everything but the tail (head)

定義は最後にあります。

これらの関数は、次のように引数を受け入れることができます。

f=foo/bar/my_image_file.0076.jpg
e $f
--> jpg
E $f
--> foo/bar/my_image_file.0076

または、パイプからの入力を受け入れます。これは、私が本当に欲しかった tcsh の機能です。

echo $f|E|e
--> 0076

またはもちろん、組み合わせ:

T $f|t
--> bar

そして、パイプを介して多くのファイルを受け入れることに気づきました:

ls foo/bar/
--> my_image_file.0075.jpg  my_image_file.0076.jpg
ls foo/bar/ |E|e
--> 0075
--> 0076

定義:

#If there are no args, then assume input comes from a pipe.

function e(){
    if [ $# -ne 0 ]; then
        echo ${1##*.}  
    else
        while read data; do
            echo  ${data##*.}   ; 
        done
    fi
}

function E(){
    if [ $# -ne 0 ]; then
        echo ${1%.*} 
    else
        while read data; do
            echo ${data%.*}
        done
    fi
}

function t(){
    if [ $# -ne 0 ]; then
        echo ${1##*/}  
    else
        while read data; do
            echo  ${data##*/}   ; 
        done
    fi
}

function T(){
    if [ $# -ne 0 ]; then
        echo ${1%/*} 
    else
        while read data; do
            echo ${data%/*}
        done
    fi
}
于 2011-03-01T22:23:06.430 に答える