4

パターンの複数のインスタンスを含むプレーンテキストファイルが$$DATABASE_*$$あり、アスタリスクは任意の文字列にすることができます。インスタンス全体をアスタリスク部分にあるものに置き換えたいのですが、小文字です。

テストファイルは次のとおりです。

$$DATABASE_GIBSON$$

test me $$DATABASE_GIBSON$$ test me

$$DATABASE_GIBSON$$ test $$DATABASE_GIBSON$$ test

$$DATABASE_GIBSON$$ $$DATABASE_GIBSON$$$$DATABASE_GIBSON$$

必要な出力は次のとおりです。

gibson

test me gibson test me

gibson test gibson test

gibson gibsongibson

sed / awk / tr / perlでこれを行うにはどうすればよいですか?

4

9 に答える 9

3

これが私が最終的に使用したperlのバージョンです。

perl -p -i.bak -e 's/\$\$DATABASE_(.*?)\$\$/lc($1)/eg' inputFile
于 2012-10-25T19:25:49.093 に答える
1

これは複雑な例で動作します。

perl -ple 's/\$\$DATABASE_(.*?)\$\$/lc($1)/eg' filename.txt

より簡単な例については、次のとおりです。

echo '$$DATABASE_GIBSON$$' | sed 's@$$DATABASE_\(.*\)\$\$@\L\1@'

では、\L小文字を意味します (必要\Eに応じて停止します)

于 2012-10-25T17:16:44.293 に答える
1

残念ながら、awk には簡単で確実な方法はありませんが、1 つの方法を次に示します。

$ cat tst.awk
{
   gsub(/[$][$]/,"\n")

   head = ""
   tail = $0

   while ( match(tail, "\nDATABASE_[^\n]+\n") ) {
      head = head substr(tail,1,RSTART-1)
      trgt = substr(tail,RSTART,RLENGTH)
      tail = substr(tail,RSTART+RLENGTH)

      gsub(/\n(DATABASE_)?/,"",trgt)

      head = head tolower(trgt)

   }

   $0 = head tail

   gsub("\n","$$")

   print
}

$ cat file
The quick brown $$DATABASE_FOX$$ jumped over the lazy $$DATABASE_DOG$$s back.
The grey $$DATABASE_SQUIRREL$$ ate $$DATABASE_NUT$$s under a $$DATABASE_TREE$$.
Put a dollar $$DATABASE_DOL$LAR$$ in the $$ string.

$ awk -f tst.awk file
The quick brown fox jumped over the lazy dogs back.
The grey squirrel ate nuts under a tree.
Put a dollar dol$lar in the $$ string.

$$ を改行文字に変換するトリックに注意してください。これにより、マッチ (RE) でその文字を無効にすることができます (つまり、「[^\n]+」の代わりに「.+」を使用した場合)。 RE マッチングでは、同じパターンが 1 つの入力行に 2 回出現した場合、一致する文字列は最初のパターンの開始から 2 番目のパターンの終了まで拡張されます。

于 2012-10-25T19:47:35.773 に答える
0

awkOPによって要求されたすべてを実行する、私が思いつくことができる最短の(GNU)ソリューションは次のとおりです。

awk -vRS='[$][$]DATABASE_([^$]+[$])+[$]' '{ORS=tolower(substr(RT,12,length(RT)-13))}1' 

アスタリスク ( *) で示される文字列に 1 つまたは複数のドル記号 ( $) や改行が含まれていても、このソウルションは機能します。

于 2013-08-28T10:10:31.737 に答える
0

これはうまくいくかもしれません(GNU sed):

sed 's/$\$/\n/g;s/\nDATABASE_\([^\n]*\)\n/\L\1/g;s/\n/$$/g' file
于 2012-10-26T08:29:14.363 に答える
0

これは、supercool コマンドの cut を使用して、非常に簡単に行うことができます:)

echo '$$DATABASE_AWESOME$$' | cut -d'$' -f3 | cut -d_ -f2 | tr 'A-Z' 'a-z'
于 2012-10-25T19:59:15.523 に答える
0
awk '{gsub(/\$\$DATABASE_GIBSON\$\$/,"gibson")}1' file
gibson

test me gibson test me

gibson test gibson test

gibson gibsongibson
于 2016-05-01T00:08:55.410 に答える
0

awk を単独で使用する:

> echo '$$DATABASE_AWESOME$$' | awk '{sub(/.*_/,"");sub(/\$\$$/,"");print tolower($0);}'
awesome

私は FreeBSD を使用しているため、これは GNU awk ではないことに注意してください。

ただし、これは bash だけを使用して実行できます。

[ghoti@pc ~]$ foo='$$DATABASE_AWESOME$$'
[ghoti@pc ~]$ foo=${foo##*_}
[ghoti@pc ~]$ foo=${foo%\$\$}
[ghoti@pc ~]$ foo=${foo,,}
[ghoti@pc ~]$ echo $foo
awesome

上記の置換のうち、最後の置換 ( ${foo,,}) を除くすべては、標準の Bourne シェルで機能します。bash がない場合は、代わりtrにこの手順を使用できます。

$ echo $foo
AWESOME
$ foo=$(echo "$foo" | tr '[:upper:]' '[:lower:]')
$ echo $foo
awesome
$ 

更新

コメントによると、OPが本当に望んでいるのは、部分文字列が含まれているテキストから部分文字列を取り除くことです。彼の質問で提供されています。

> echo 'foo $$DATABASE_KITTENS$$ bar' | sed -nE '/\$\$[^$]+\$\$/{;s/.*\$\$DATABASE_//;s/\$\$.*//;p;}' | tr '[:upper:]' '[:lower:]'
kittens

また、たまたま( FreeBSD ポートpcregrepからの) パス上にある場合は、先読みを使用して代わりにそれを使用できます。devel/pcre

> echo 'foo $$DATABASE_KITTENS$$ bar' | pcregrep -o '(?!\$\$DATABASE_)[A-Z]+(?=\$\$)' | tr '[:upper:]' '[:lower:]'
kittens

(これを読んでいる Linux ユーザーの場合: これは を使用するのと同じgrep -Pです。)

そして純粋なbashで:

$ shopt -s extglob
$ foo='foo $$DATABASE_KITTENS$$ bar'
$ foo=${foo##*(?)\$\$DATABASE_}
$ foo=${foo%%\$\$*(?)}
$ foo=${foo,,}
$ echo $foo
kittens

これら 3 つの更新されたソリューションのいずれも、同じ入力行に複数のタグ付きデータベース名が存在する状況を処理しないことに注意してください。それは質問の要件としても述べられていませんが、私はただ言っています....

于 2012-10-25T17:48:38.547 に答える
-1

echo $$DATABASE_WOOLY$$ | awk '{print tolower($0)}'

awk は、これまでの入力 (この場合は最初の引数) を受け取り、tolower関数を使用して結果を返します。

あなたのbashスクリプトでは、このようなことをして変数を使うことができますDBLOWER

DBLOWER=$(echo $$DATABASE_WOOLY$$ | awk '{print tolower($0)}');
于 2012-10-25T17:22:47.983 に答える