tutorial tipos fisiologia sed

tipos - ¿Por qué los delimitadores alternativos no funcionan con sed-e ''/ pattern/s/a/b/''?



sed shell (5)

Esta pregunta ya tiene una respuesta aquí:

Aquí hay algo que he descubierto que no tiene sentido.

Salida de cat config.h :

define somevar foo // Sample variable

Esta versión del comando funciona para cambiar foo a bar y preservar los comentarios:

sed -e ''/somevar/s/foo/bar/'' config.h

Esto no funciona:

sed -e ''|somevar|s|foo|bar|'' config.h

Da este error:

sed: -e expresión # 1, char 1: comando desconocido: `| ''

Curiosamente, esto funciona:

sed -e ''/somevar/s|foo|bar|'' config.h

Quizás me esté faltando alguna parte de la documentación. Parece muy extraño tener dos delimitadores diferentes en el mismo comando sed.

¿Error o característica?


Absolutamente puede usar delimitadores alternativos para la dirección coincidente ( /regex/ ), pero necesita decirle a sed que tiene la intención de hacer coincidir con ese delimitador. La forma en que lo haces es con una barra invertida inicial / . Entonces tu orden puede ser:

sed -e ''/|somevar|s|foo|bar|'' config.h

o simplemente con la misma facilidad:

sed -e ''/%somevar%s|foo|bar|'' config.h

Referencia: POSIX referencia para sed


Característica. En

sed -e ''/somevar/s/foo/bar/'' config.h

El /somevar/ es una dirección . Las direcciones deben ser distinguibles de otras funciones, como y (yank), i (insert), a (append) y muchas más. En general, los comandos sed se analizan como

[address[,address]]function[arguments]


Esto funcionará:

sed -e ''/|somevar|s|foo|bar|''

La página del man de GNU sed es bastante clara al respecto:

/regexp/ Match lines matching the regular expression regexp. /cregexpc Match lines matching the regular expression regexp. The c may be any character.

Es decir, la c puede ser cualquier carácter, pero el inicio es obligatorio.

No tengo FreeBSD, pero de acuerdo con @bonsaiviking la página del man también es muy clara:

El delimitador de apertura debe ir precedido por una barra invertida, a menos que sea una barra diagonal.

Por otro lado, en OSX esto no está claro en absoluto:

In a context address, any character other than a backslash (``/''') or newline character may be used to delimit the regular expression. Also, putting a backslash character before the delimiting character causes the character to be treated literally. For example, in the context address /xabc/xdefx, the RE delimiter is an ``x'''' and the second ``x'''' stands for itself, so that the regular expression is ``abcxdef''''.

Observe que el ejemplo allí usa /xpatternx lugar de solo xpatternx . Esa es toda la pista que da, no deja claro que xpatternx no funcionará.

Basado en el argumento de @that-other-guy , tiene sentido que sed (y otros idiomas como perl como @Birei señaló @Birei ) necesitan esta pista adicional para funcionar correctamente.


Mi voto es para la función .

Son dos comandos diferentes, el de búsqueda /.../ y el de sustitución, s/.../.../ . Por lo que sé, solo permite cambiar el separador del comando de sustitución.

En perl es similar. Puede realizar una búsqueda de expresiones regulares con /.../ pero si desea cambiar el separador, debe marcarlo explícitamente como una búsqueda con la m , como: m|...| .

Supongo que estará relacionado con algún problema de análisis léxico, pero no sé la razón, sin embargo.


Permitir diferentes delimitadores para /pattern/ introduciría la ambigüedad de análisis.

¿ ispaghetti supone que ispaghetti es como /spaghett/ , o se supone que debe insertar texto como i spaghetti ?

Con y no hay tal ambigüedad. Cuando ve cualquiera de esos caracteres, conoce el comando que está leyendo y luego puede interpretar el siguiente carácter como un delimitador.

Podríamos resolver esta ambigüedad para /pattern/ si lo empezáramos con un carácter similarmente reconocible, y de hecho sed tiene un especificador de dirección separado para esto: barra diagonal inversa, como en /|pattern| (esto no es lo mismo que escapar).

Por lo tanto, podemos escribir /|pattern|s|foo|bar| .

La dirección y los comandos de edición son independientes, por lo que /$pattern$s_foo_bar_ y /pattern/s#foo#bar# funcionan.