ある文字やパターンから別の文字やパターンに移動するには?

ある文字やパターンから別の文字やパターンに移動するには?

行全体ではなく、特定の文字やパターンから別の特定の文字やパターンに文字列を把握したいと思います。

たとえば、

$ > echo "The brown fox jumps over the lazy dog" | grep -option "b" "s"
brown fox jumps

$ > echo "The brown fox jumps over the lazy dog" | grep -option "the l" "g"
the lazy dog

実際に必要なのは、dirs -v次のことができるようにパスを移動するときです。

$ > ls -AF
file.txt   github/    .vim/

$ > dirs -v
0    ~
1    ~/.vim/pack/themes
2    ~/.vim/colors
3    ~/github/dirname
4    ~/github/repo/

$ > mv -v file.txt $(dirs -v | grep 2 | grep -option "~" "colors")
renamed 'file.txt' -> '~/.vim/colors/file.txt'

~含まれている行のみを一致させるためにgrepを2回使用しました2。私の.zshrcでシェル関数/エイリアスでこれを行う方法はありますか?


mv file.txt ~2回答:私は以下の答えの1つを使用しました。私がこのようなことができるとは思わなかったんです、ハハ。

また、以下の答えの1行を.zshrcに入れました。

function grepo () { grep -Po "${1}.*?${2}" }
alias -g GO='| grepo'

これにより、次のように使用できます。

$ > echo "the brown fox jumps over the lazy dog" GO b s
brown fox jumps

$ > echo "the brown fox jumps over the lazy dog" GO "the l" g
the lazy dog

$ > echo "the brown fox jumps over the lazy dog" GO fox over
fox jumps over

私の問題では動作しませんが、何らかの理由で考えることはできません。

$ > ls -AF
file.txt   github/    .vim/

$ > dirs -v
0    ~
1    ~/.vim/pack/themes
2    ~/.vim/colors
3    ~/github/dirname
4    ~/github/repo/

$ > mv file.txt $(dirs -v GO "~/.v" "themes")
mv: cannot move 'file.txt' to '~/.vim/pack/themes': No such file or directory

答え1

では、zsh次のことができます。

$ str='The brown fox jumps over the lazy dog'
$ print -r -- ${(SM)str#b*s}
brown fox jumps

ksh${str#pattern}演算子の削除最短pattern文字列の先頭から一致する文字列です。 (Sのためサブストリング)パラメータ拡張フラグパターンが一致に限定されないように拡張最初に、しかし最初からできるだけ近くに。フラグM(龍マッチ)は、これらの拡散演算子が一致する部分を削除するのではなく、一致するコンテンツに拡張することを可能にします。

あなたを許可する##代わりに使用してください#最長変える最短および%/%%文字列の最後にパターンを探します。

*?PCREマッチングを実行し、貪欲ではない演算子を使用することもできます。

$ zmodload zsh/pcre
$ [[ $str -pcre-match 'b.*?s' ]] && print -r -- $MATCH
brown fox jumps

または:

$ set -o rematchpcre
$ [[ $str =~ 'b.*?s' ]] && print -r -- $MATCH
brown fox jumps

ただし、特定のユースケースでは次のようにします。

mv file.txt ~2

ファイルをディレクトリスタックの2番目のディレクトリに移動します。

設定が正しい場合は、[次へ]をクリックすると、完了時に次の~<number>内容に対応する内容が表示されます。Tab~+

$ MVファイル〜+Tab
完全なディレクトリスタック
1 - ~/install/cvs/zsh/Config
2 - 〜
3 - / usr
4 - 〜空
5 - 〜
6 - /

~/.zshrcこの出力を生成する最小値は次のとおりです。

set -o autopushd
autoload -Uz compinit
compinit
zstyle ':completion:*' menu select=0
zstyle ':completion:*' verbose true
zstyle ':completion:*' format 'Completing %d'

compinstall(初心者にやさしい方法で仕上げのカスタマイズを参照)

答え2

PCRE正規表現で遅延一致を使用します(.*?)。

$ str='The brown fox jumps over the lazy dog'

$ grep -Po 'b.*?s' <<<"$str"
brown fox jumps

$ grep -Po 'the l.*?g' <<<"$str"
the lazy dog

より基本的な正規表現に対する同様の解決策がありますが、単一文字にのみ適用されます(右側)。

$ grep -o 'b[^s]*s' <<<"$str"
brown fox jumps

$ grep -o 'the l[^g]*g' <<<"$str"
the lazy dog

上記の項目はすべて一致します。最初初期テキスト以降最初最終テキスト(含む)。

答え3

これを行うより簡単で信頼性の高い方法があります。

zshから、使用dirstack変えるzsh は変数拡張のための素晴らしい仕事をしないので、引用は必要ありません。

mv file.txt $dirstack[2]

親ディレクトリが必要な場合は追加できます。履歴修飾子 :h。たとえば、ファイルをディレクトリスタックエントリの親エントリに移動するには、を使用しますmv file.txt $dirstack[2]:h。ファイルを親エントリの親エントリに移動するには、mv file.txt $dirstack[2]:h:hまたはを使用しますmv file.txt $dirstack[2]:h2

また、使用することができますパラメータ拡張ディレクトリ名を変更するように設定しますが、より複雑になります。

または、ターゲットディレクトリを変更するには、afterを押すとTabzsh$dirstack[2]は変数拡張をその値に置き換えます。

バッシュから、使用DIRSTACK変える引用符と中括弧が必要です。

mv file.txt "${DIRSTACK[2]}"

あなたは使用することができますパラメータ拡張結果の値に基づいて構築します。たとえば、ファイルをディレクトリスタックエントリの親ディレクトリに移動するにはmv file.txt "${DIRSTACK[2]#/*}"


$ > mv -v file.txt $(dirs -v | grep 2 | grep -option "~" "colors")

壊れやすいです。ディレクトリ名に2?が含まれているか、スタックに12以上のディレクトリがある場合。コマンド置換の結果、チルダが拡張されないため、機能しません。あなたは次のようなものを使用する必要があります

"$(HOME=/none dirs -v | grep '^ *2[^0-9]' | sed 's:^[^/]*::')"
  • 二重引用符でコマンド置換を囲みます。生成されたディレクトリ名にスペースが含まれている場合。
  • 2行の先頭でのみ一致します(先行スペースは許可されています)。
  • 2複数桁の数字の先頭であれば一致しません。
  • sedを使用して、ディレクトリ名が開始される前のすべてのエントリを削除します。HOME実行時に存在しないパスに設定されるため、ディレクトリdirs名はスラッシュで始まることが保証されます。
  • ディレクトリ名の一部だけを選択したい場合は、追加のgrepを使用するだけです。

awkはより良いツールかもしれませんが、より一般的な単一のツール(awk)を使用するのか、それともより特殊化されたツール(grep、sedなど)の組み合わせを使用するのかは、ある程度好みの問題です。

"$(HOME=/none dirs -v | awk '$1 == 2 {sub(/^[ \t0-9]+/, ""); print; exit}')"

1完了とキーバインディング設定によっては、異なるキーが必要になる場合があります。可能性について議論することは、この回答の範囲外です。
²空の単語を削除することを除いて、ディレクトリスタックが十分に深いことを確認する限り問題はありません。
³ディレクトリ名にスペース(またはワイルドカード)が含まれていない場合は、引用符は必要ありません。

関連情報