1

たくさんのファイルのすべての色の値を反転させたいです。色はすべて16進形式で#ff3300あるため、sedコマンドを使用して文字ごとに反転を行うことができます。

y/0123456789abcdef/fedcba9876543210/

すべてのカラーマッチをループして、sedまたはawkでchar変換を行うにはどうすればよいですか?

編集:

サンプル入力:

random text... #ffffff_random_text_#000000__
asdf#00ff00
asdfghj

必要な出力:

random text... #000000_random_text_#ffffff__
asdf#ff00ff
asdfghj
4

4 に答える 4

2

編集:私はあなたの編集に従って私の応答を変更しました。

OK、sed処理が困難になる可能性があります。awk多かれ少なかれ簡単にトリックを行うことができますが、私perlはこのタスクのためにはるかに簡単だと思います:

$ perl -pe 's/#[0-9a-f]+/$&=~tr%0123456789abcdef%fedcba9876543210%r/ge' <infile >outfile

基本的に、パターンを見つけてから、右側を実行します。これにより、一致時にtrが実行され、そこで値が置き換えられます。

于 2012-07-05T09:51:57.053 に答える
2

反転は実際には減算です。ヘクスを反転するには、それをから減算するだけですffffff
これを念頭に置いて、各行を処理し、ヘクスを抽出し、それらを反転して、それらを行に戻すための簡単なスクリプトを作成できます。


これはBash(配列などを参照printf -v+=のみを使用しています(外部ツールはありません):

#!/usr/bin/env bash

[[ -f $1 ]] || { printf "error: cannot find file: %s\n" "$1" >&2; exit 1; }

while read -r; do
    # split line with '#' as separator
    IFS='#' toks=( $REPLY )
    for tok in "${toks[@]}"; do
        # extract hex
        read -n6 hex <<< "$tok"
        # is it really a hex ?
        if [[ $hex =~ [0-9a-fA-F]{6} ]]; then
            # compute inversion
            inv="$((16#ffffff - 16#$hex))"
            # zero pad the result
            printf -v inv "%06x" "$inv"
            # replace hex with inv
            tok="${tok/$hex/$inv}"
        fi
        # build the modified line
        line+="#$tok"
    done
    # print the modified line and clean it for reuse
    printf "%s\n" "${line#\#}"
    unset line
done < "$1"

次のように使用します。

$ ./invhex infile > outfile

テストケース入力:

random text... #ffffff_random_text_#000000__
asdf#00ff00
bdf#cvb_foo
asdfghj
#bdfg

処理された出力:

random text... #000000_random_text_#ffffff__
asdf#ff00ff
bdf#cvb_foo
asdfghj
#bdfg
于 2012-07-05T13:14:59.687 に答える
2

これはあなたのために働くかもしれません(GNU sed):

sed '/#[a-f0-9]\{6\}\>/!b
s//\n&/g
h
s/[^\n]*\(\n.\{7\}\)[^\n]*/\1/g
y/0123456789abcdef/fedcba9876543210/
H
g
:a;s/\n.\{7\}\(.*\n\)\n\(.\{7\}\)/\2\1/;ta
s/\n//' file

説明:

  • /#[a-f0-9]\{6\}\>/!b必要なパターンを含まない行でベイルアウトする
  • s//\n&/gすべてのパターンに改行を追加します
  • hこれをホールドスペースにコピーします
  • s/[^\n]*\(\n.\{7\}\)[^\n]*/\1/g必要なパターン以外のすべてを削除します
  • y/0123456789abcdef/fedcba9876543210/パターンを変換します
  • H新しいパターンをホールドスペースに追加します
  • gパターンスペースをホールドスペースの内容で上書きします
  • :a;s/\n.\{7\}\(.*\n\)\n\(.\{7\}\)/\2\1/;ta古いパターンを新しいパターンに置き換えます。
  • s/\n//コマンドから改行アーティファクトを削除しますH
于 2012-07-05T16:06:16.690 に答える
1

これは動作します...

cat test.txt |sed -e 's/\#\([0123456789abcdef]\{6\}\)/\n\#\1\n/g' |sed -e ' /^#.*/ y/0123456789abcdef/fedcba9876543210/' | awk '{lastType=type;type= substr($0,1,1)=="#";} type==lastType && length(line)>0 {print line;line=$0} type!=lastType {line=line$0} length(line)==0 {line=$0} END {print line}'

最初のsedコマンドは、16進コードの前後に改行を挿入します。その後、ハッシュで始まるすべての行を置換することができます。おそらく、行を再びマージするための洗練されたソリューションがありますが、awkコマンドがその役割を果たします。唯一の前提は、2つの16進コードが直接続くことはないということです。その場合、このステップを修正する必要があります。

于 2012-07-05T11:50:24.823 に答える