sedを使用して任意の場所にある文字を置き換えますか?

sedを使用して任意の場所にある文字を置き換えますか?

ファイルの任意の場所にある文字を置き換えようとしています。私のファイルは次のとおりです。

aab  
babab  
abab  

「c」を任意の文字に置き換えようとしています。したがって、出力は次のようになります。

aab  
bcbab  
abab 

すべての改行を削除し、new_string.txtファイルに保存してからsedを試しましたが、うまくいきませんでした。

これは私が試したコードです。

rand1="$(shuf -i 0-$tot_len -n 1)"
sed "s/^\(.\{"${rand1}"\}\)./\1G/" new_string.txt

継続エラーが発生します。

sed: -e expression #1, char 25: Invalid content of \{\}

答え1

変数には中括弧は必要なく、変数も引用符で囲む必要があります。使用:

sed "s/^\(.\{$rand1\}\)./\1G/" new_string.txt

アップデート:コメントで述べたように:

元のコードは問題ありませんが、整数が大き$rand1すぎますsed。可能な最大値は32767GNUでsedあり、sedまだ16ビット整数のみが必要であることがわかりました。

これにより、システム正規表現ライブラリの制限を得ることができます(GNUはsed通常組み込みバージョンを使用しますが)。

$ getconf RE_DUP_MAX
32767

POSIXでは、この制限は少なくとも_POSIX_RE_DUP_MAX255でなければなりません。これは移植性を期待できる最大値です(一部のシステム(SolarisやOS / Xなど)にはこれらの制限があります)。

答え2

GNUシステムで文字(改行を除く)をランダムに置き換えるには、次のようにします。

file=myfile.txt
offset=$(grep -bo . < "$file" | cut -d: -f1 | shuf -n1)
[ -z "$offset" ] || # file doesn't have non-newline characters
  printf c | dd bs=1 seek="$offset" of="$file" conv=notrunc status=none

(以前のバージョンのGNU dd(8.20より前)の場合status=noneに置き換えてください2> /dev/null。)

grep -bo . < "$file"ファイルの改行文字ではなく、各文字のバイトオフセットを提供します。たとえば、UTF-8でエンコードされたファイルには次のものが含まれます。

$3
£1
€2

これは私たちに以下を提供します。

$ grep -bo . < "$file"
0:$
1:3
3:£
5:1
7:€
10:2

の場合、cut -d: -f1最初のコロンの前の部分を維持します。次に、これらのオフセットの1つをランダムに選択しますshuf -n1

これは、置換文字が置換される文字と同じサイズであると仮定する。たとえば、上記の£(2バイト)をc(1バイト)に置き換えると、ファイルの後にc誤った文字が表示されます。

この問題を解決するにはデータを移動する必要があるため、ファイルを上書きすることはできません。

次のようなものが必要です。

perl -C -0777 -pi -e "substr \$_, $offset, 1, 'c'" -- "$file"

代わりに。とともに-Cperlコンポジションのロケールを尊重します。特徴-0777 -p開いている喫煙内容物を$file飲み込むモード$_(参照:perl -ne '...'実行のセキュリティリスク*この建設の安全問題のため)。コードの実行後にファイルに書き換える-pi内部編集機能を提供します。次に、指定されたオフセットで1文字の置換を$_呼び出します。substrc

答え3

\n新しいGNU sedを使用すると、ewlineを削除せずにこれを行うことができます。

sed -z "s/./@/$(($RANDOM%$(wc -m < file.txt)))" file.txt

答え4

この試み:

sed 's/^\(.\{'"${rand1}"'\}\)./\1G/'  new_string.txt

関連情報