Contar las nuevas líneas finales utilizando utilidades POSIX, GNU coreutils o Perl.
Estoy buscando formas de contar el número de saltos de línea al final de los datos, que pueden ser binarios, ya sea:
– leídos desde la entrada estándar
– o ya en una variable de shell (entonces, por supuesto, “binario” excluye al menos 0x0)
usando utilidades POSIX o coreutils o tal vez Perl.
Esto debería funcionar sin archivos temporales o FIFOs.
Cuando la entrada está en una variable de shell, ya tengo la siguiente solución (posiblemente fea pero) funcionando:
original_string=$'abc\n\n\def\n\n\n'
string_without_trailing_newlines="$( printf '%s' "${original_string}" )"
printf '%s' $(( ${#original_string}-${#string_without_trailing_newlines} ))
que devuelve 3
en el ejemplo anterior.
La idea anterior es simplemente restar las longitudes de las cadenas y usar la “característica” de la sustitución de comandos que descarta cualquier salto de línea final.
Casos de prueba:
printf '' | función resulta en: 0
printf '\n' | función resulta en: 1
printf '\n\n' | función resulta en: 2
printf '\n\n\n' | función resulta en: 3
printf 'a' | función resulta en: 0
printf 'a\n' | función resulta en: 1
printf 'a\n\n' | función resulta en: 2
printf '\na\n\n' | función resulta en: 2
printf 'a\n\nb\n' | función resulta en: 1
Para los casos especiales en los que NUL
forma parte de la cadena (lo cual de todas formas solo funciona al leer desde la entrada estándar, no al proporcionar la cadena en la variable de la shell), los resultados son indefinidos pero generalmente deberían ser cualquiera de los siguientes:
printf '\n\x00\n\n' | función resulta en: 1
printf 'a\n\n\x00\n' | función resulta en: 2
que cuenta los saltos de línea hasta el NUL
o:
printf '\n\x00\n\n' | función resulta en: 2
printf 'a\n\n\x00\n' | función resulta en: 1
que cuenta los saltos de línea después del NUL
o:
printf '\n\x00\n\n' | función resulta en: 3
printf 'a\n\n\x00\n' | función resulta en: 3
que ignora cualquier NUL
“trailing”, siempre y cuando estén justo antes, dentro o justo después de los NUL
finales
o:
dando error
davy.ai
Una posible solución en shell que funciona tanto para leer desde la entrada estándar como desde una variable de shell es:
Explicación:
string_without_trailing_nuls
se crea eliminando cualquier nulo final (si está presente) de la cadena, utilizando el operador%
con un patrón de comodín.trailing_newlines
se crea contando los saltos de línea (incluyendo nulos) al final de la cadena utilizando los comandos tail, tr y wc.Esta solución debería funcionar correctamente para cualquier combinación de caracteres imprimibles y no imprimibles, incluyendo nulos, y debería ser compatible con POSIX.
Tenga en cuenta que las pruebas de casos proporcionadas en la indicación no son una sintaxis válida de shell, ya que el comando
printf
requiere una cadena de formato (por ejemplo,printf '%s\n' ''
en lugar deprintf ''
), y las comillas invertidas en lugar del símbolo acento grave para invocar la sustitución de comandos (por ejemplo,echo `command`
en lugar deecho `command`
).