string - script - Sustituir todos los caracteres entre dos cadenas por char ''X'' usando sed
sed reemplazar/ (3)
Puede evitar %26
haciendo esto:
a=''CPI.%26Name%3dJASON%26Pwd%3dBOTTLE%26Name%3dCOTT''
echo "$a" |sed -E '':a;s/(%3dX*)([^%X]|%[013-9a-f][0-9a-f]|%2[0-5789a-f])//1X/g;ta;''
Tenga en cuenta que cada carácter codificado %xx
cuenta para una X.
En un script de Bash, estoy tratando de reemplazar en el archivo los caracteres entre dos cadenas dadas por ''X''. Tengo muchos pares de cuerdas, entre los cuales quiero que ocurra el reemplazo de los caracteres por ''X''.
En el siguiente código, la primera cadena del par se declara en cpi_list array. La segunda cadena del par siempre es %26
o &
o ENDOFLINE
Esto es lo que estoy haciendo.
# list of "first" or "start" string
declare -a cpi_list=(''%26Name%3d'' ''%26Pwd%3d'')
# This is the "end" string
myAnd=/%26
newfile="inputlog.txt"
for item in "${cpi_list[@]}";
do
sed -i -e :a -e "s//($item[X]*/)[^X]/(.*"$myAnd"/)//1X/2/;ta" $newfile;
done
La entrada
CPI.%26Name%3dJASON%26Pwd%3dBOTTLE%26Name%3dCOTT
CPI.%26Name%3dVoorhees&machete
Quiero hacerlo
CPI.%26Name%3dXXXXX%26Pwd%3dXXXXXX%26Name%3dXXXX
CPI.%26Name%3dXXXXXXXX&machete
PD: El último elemento también necesita cambiar %26Name%3dCOTT
a %26Name%3dXXXX
aunque no haya final %26
porque estoy buscando %26
como punto final o el END OF THE LINE
Pero de alguna manera no está funcionando.
Esto funcionará en cualquier awk llamado desde cualquier shell en cualquier instalación de UNIX:
$ cat tst.awk
BEGIN {
begs = "%26Name%3d|%26Pwd%3d"
ends = "%26|&"
}
{
head = ""
tail = $0
while( match(tail, begs) ) {
tgtStart = RSTART + RLENGTH
tgt = substr(tail,tgtStart)
if ( match(tgt, ends) ) {
tgt = substr(tgt,1,RSTART-1)
}
gsub(/./,"X",tgt)
head = head substr(tail,1,tgtStart-1) tgt
tail = substr(tail,tgtStart+length(tgt))
}
$0 = head tail
print
}
$ cat file
CPI.%26Name%3dJASON%26Pwd%3dBOTTLE%26Name%3dCOTT
CPI.%26Name%3dVoorhees&machete
$ awk -f tst.awk file
CPI.%26Name%3dXXXXX%26Pwd%3dXXXXXX%26Name%3dXXXX
CPI.%26Name%3dXXXXXXXX&machete
Al igual que con una sustitución sed, cualquier metacaracter regexp en las cadenas de inicio y final tendría que ser escapado o tendríamos que usar un bucle con index()
s en lugar de match()
así que haríamos matching de cadena en lugar de regexp pareo.
No es bonito pero puedes usar perl:
$ s1="CPI.%26Name%3dJASON%26Pwd%3dBOTTLE%26Name%3dCOTT"
$ echo "$s1" | perl -lne ''if (/(?:^.*%26Name%3d)(.*)(?:%26Pwd%3d)(?:.*%26Name%3d)(.*)((?:%26Pwd%3d)|(?:$))/) {
$i1=$-[1];
$l1=$+[1]-$-[1];
$i2=$-[2];
$l2=$+[2]-$-[2];
substr($_, $i1, $l1, "X"x$l1);
substr($_, $i2, $l2, "X"x$l2);
print;
}''
CPI.%26Name%3dXXXXX%26Pwd%3dBOTTLE%26Name%3dXXXX
Eso es para dos pares como el ejemplo. N pares en una línea será una ligera modificación.