sedを使用して複雑な文字列を検索して置換する(できれば正規表現を使用する)

次の内容のファイルがあります:

<username><![CDATA[name]]></username> <password><![CDATA[password]]></password> <dbname><![CDATA[name]]></dbname> 

そして、1行目の「name」を「something」に、2行目の「password」を「somethingelse」に、「name」をで変更するスクリプトを作成する必要があります。 「somethingdifferent」の3行目。ファイル内で発生するこれらの順序に依存することはできないため、最初に出現する「name」を「something」に置き換え、2番目に出現する「name」を「somethingdifferent」に置き換えることはできません。実際には、周囲の文字列を検索して、正しいものを見つけて置き換えることを確認する必要があります。

これまで、このコマンドを試し、最初の「名前」の出現箇所を見つけて置き換えました。

sed -i "s/<username><![CDATA[name]]><\/username>/something/g" file.xml 

ただし、機能していないので、これらの文字の一部をエスケープする必要があるかもしれないと考えています。

理想的には、私」 d regexを使用して、2つの「username」オカレンスを一致させ、「name」のみを置き換えることができるのが大好きです。このようなものですが、sedを使用します:

<username>.+?(name).+?</username> 

括弧内の内容を「何か」に置き換えます。

これは可能ですか?

コメント

  • 非常に工夫されていない限り、ほとんどすべての正規表現ベースのソリューションにはリスクが伴うことに注意してください。入力形式が変更されるたびに中断します。正規表現は、XML、SGML、または派生物(これは私には見えます)を扱うには不適切な選択です。
  • 承認されました!たとえば、XQueryの使用を検討してください: w3schools.com/xquery/default.asp 。これは、XMLコンテンツを取得および操作するためのW3C標準です。

回答

sed -i -E "s/(<username>.+)name(.+<\/username>)/\1something\2/" file.xml 

これは、あなたが探しているものだと思います。

説明:

  • 最初の部分の括弧は、グループ(実際には文字列)を定義します。 2番目の部分で再利用できます
  • \1\2などは2番目の部分への参照です。最初の部分でキャプチャされたi番目のグループ(番号付けは1から始まります)
  • -Eは、拡張正規表現を有効にします(+とグループ化)。

コメント

  • +1は-Eオプション
  • it (original name) + "-E"という名前のバックアップファイルを残します。
  • OSXでは' sed:1:" s /(<ユーザー名>。+)name(。+ … ":\ 1ではありませんRE 'で定義されています。この質問の正確な例をファイルに貼り付けました。次に、そのファイルに対してこの回答からコマンドを実行しました。 OSXの構文が異なる可能性がありますか?
  • sedのgnuバージョンは" -E "パラメーターをサポートしていますが、サポートしていません公式。 'はマンページにも記載されていません。拡張正規表現を使用する場合は、代わりに" -r "パラメーターを使用する必要があります。
  • @ deweydb この回答によると、\(\)を使用する必要があります(および)の代わりに。

回答

sed -e "/username/s/CDATA\[name\]/CDATA\[something\]/" \ -e "/password/s/CDATA\[password\]/CDATA\[somethingelse\]/" \ -e "/dbname/s/CDATA\[name\]/CDATA\[somethingdifferent\]/" file.txt 

sがsedに通知する前の/username/文字列「username」を含む行でのみ機能します。

コメント

  • エレガントで効率的で、ケースに完全に適合します。 +1

回答

sedが難しい場合要件として、代わりに専用ツールを使用することをお勧めします。

ファイルが有効なXML(3つのXMLに見えるタグだけでなく)の場合は、 XMLStarletを使用できます。

xml ed -P -O -L \ -u "//username/text()" -v "something" \ -u "//password/text()" -v "somethingelse" \ -u "//dbname/text()" -v "somethingdifferent" file.xml 

上記は、通常の式では解決が難しい状況でも機能します。

  • 現在の値を指定せずにタグの値を置き換えることができます。
  • エスケープされてCDATAに含まれていない場合でも、値を置き換えることができます。
  • タグには属性があります。
  • 同じ名前のタグが複数ある場合は、タグの出現だけを簡単に置き換えることができます。
  • 変更されたXMLをインデントすることでフォーマットできます。

上記の簡単なデモンストレーション:

bash-4.2$ cat file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[name]]></username> <password>password</password> <dbname foo="bar"><![CDATA[name]]></dbname> </apprentice> </sith> bash-4.2$ xml ed -O -u "//apprentice/username/text()" -v "something" -u "//password/text()" -v "somethingelse" -u "//dbname/text()" -v "somethingdifferent" file.xml <sith> <master> <username><![CDATA[name]]></username> </master> <apprentice> <username><![CDATA[something]]></username> <password>somethingelse</password> <dbname foo="bar"><![CDATA[somethingdifferent]]></dbname> </apprentice> </sith> 

回答

$ sed -e "1s/name/something/2" \ -e "3s/name/somethingdifferent/2" \ -e "s/password/somethingelse/2" sample.xml 

アドレスを使用するだけで行番号を示す「s」の前の番号のs。

また、最後の番号は、sedに、最初の一致を置き換えるのではなく、2番目の一致を置き換えるように指示します。一致。

回答

正規表現の部分で\[.*^$/を引用する必要があります交換部品のsコマンドと\&/、および改行。正規表現は基本的な正規表現であり、さらにsコマンドの区切り文字を引用符で囲む必要があります。

/を引用する必要がないように、別の区切り文字を選択できます。代わりにその文字を引用する必要がありますが、通常、区切り文字を変更するポイントは、置換するテキストまたは置換テキストのいずれにも含まれないものを選択することです。

sed -e "s~<username><!\[CDATA\[name\]\]></username>~<username><![CDATA[something]]></username>~" 

グループを使用して、置換テキストの一部の部分を繰り返さないようにし、これらの部分のバリエーションに対応できます。

sed -e "s~\(<username><!\[[A-Z]*\[\)name\(\]\]></username>\)~\1something\2~" sed -e "s~\(<username>.*[^A-Za-z]\[\)name\([^A-Za-z].*</username>\)~\1something\2~" 

回答

「名前」の単語を「何か」の単語に置き換えるには、次を使用します。

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml 

これにより、指定された単語のすべての出現箇所が置き換えられます。

これまでのところ、すべてが標準出力に出力されているため、次を使用できます。

sed "s/\(<username><\!\[[A-Z]*\[\)name\]/\1something/g" file.xml > anotherfile.xml 

変更を別のファイルに保存します。

回答

Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... -r, --regexp-extended use extended regular expressions in the script. 

プロパティファイルの値を置き換える

sed -i -r "s/MAIL\=(.+)/MAIL\[email protected]/" etc/service.properties 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です