Es muy fácil de usar split()en JavaScript para dividir una cadena en una matriz.
¿Qué pasa con el script de shell?
Digamos que quiero hacer esto:
$ script.sh var1_var2_var3
Cuando el usuario le da dicha cadena var1_var2_var3al script.sh, dentro del script convertirá la cadena en una matriz como
array=( var1 var2 var3 )
for name in ${array[@]}; do
# some code
done
shell
shell-script
string
AGamePlayer
fuente
fuente

shellestás usando, con lobashque puedes hacerIFS='_' read -a array <<< "${string}"perlpuede hacer eso también No es un caparazón "puro", pero es bastante común.Respuestas:
Los shells tipo Bourne / POSIX tienen un operador split + glob y se invoca cada vez que deja una expansión de parámetro (
$var,$-...), una sustitución de comando ($(...)) o una expansión aritmética ($((...))) sin comillas en el contexto de la lista.En realidad, lo invocaste por error cuando lo hiciste en
for name in ${array[@]}lugar de hacerlofor name in "${array[@]}". (En realidad, debe tener cuidado de que invocar a ese operador por error es fuente de muchos errores y vulnerabilidades de seguridad ).Ese operador está configurado con el
$IFSparámetro especial (para indicar en qué caracteres dividir (aunque tenga cuidado con que el espacio, la pestaña y la nueva línea reciban un tratamiento especial allí)) y la-fopción de deshabilitar (set -f) o habilitar (set +f) laglobparte.También tenga en cuenta que si bien el
Sin$IFSera originalmente (en el shell Bourne de donde$IFSproviene) para el Sseparador, en los shells POSIX, los caracteres en$IFSdeberían verse como delimitadores o terminadores (ver a continuación un ejemplo).Entonces para dividir
_:Para ver la distinción entre separador y delimitador , pruebe:
Eso lo dividirá en
var1yvar2solo (sin elemento vacío adicional).Entonces, para que sea similar a JavaScript
split(), necesitarías un paso adicional:(tenga en cuenta que dividiría un elemento vacío
$stringen 1 (no 0 ), como JavaScriptsplit()).Para ver la pestaña de tratamientos especiales, recibir espacio y nueva línea, compare:
(donde consigues
var1yvar2) condonde se obtiene:
'',var1,'',var2,''.Tenga en cuenta que el
zshshell no invoca ese operador split + glob implícitamente así, a menos que esté enshokshemulación. Allí, debes invocarlo explícitamente.$=stringpara la parte dividida,$~stringpara la parte glob ($=~stringpara ambos), y también tiene un operador dividido donde puede especificar el separador:o para preservar los elementos vacíos:
Tenga en cuenta que existe
spara dividir , no delimitar (también con$IFSuna no conformidad POSIX conocida dezsh). Es diferente de JavaScriptsplit()en que una cadena vacía se divide en 0 (no 1) elemento.Una diferencia notable con
$IFS-splitting es que se${(s:abc:)string}divide en laabccadena, mientras que conIFS=abc, se dividiría ena,boc.Con
zshyksh93, el tratamiento especial que recibe el espacio, la pestaña o la nueva línea se puede eliminar al duplicarlos$IFS.Como nota histórica, el shell Bourne (el ancestro o los shell POSIX modernos) siempre despojó a los elementos vacíos. También tenía una serie de errores relacionados con la división y expansión de $ @ con valores no predeterminados de
$IFS. Por ejemploIFS=_; set -f; set -- $@, no sería equivalente aIFS=_; set -f; set -- $1 $2 $3....División en expresiones regulares
Ahora, para algo más cercano a JavaScript
split()que puede dividirse en expresiones regulares, necesitaría confiar en utilidades externas.En el cofre de herramientas POSIX,
awktiene unsplitoperador que puede dividirse en expresiones regulares extendidas (que son más o menos un subconjunto de las expresiones regulares similares a Perl compatibles con JavaScript).El
zshshell tiene soporte incorporado para expresiones regulares compatibles con Perl (en suzsh/pcremódulo), pero usarlo para dividir una cadena, aunque es posible, es relativamente engorroso.fuente
$PATHen:) por el contrario, generalmente se desea conservar los elementos vacíos. Tenga en cuenta que en el shell Bourne, todos los personajes estaban recibiendo el tratamiento especial, lokshcambiaron para que solo los en blanco (solo el espacio, la pestaña y la nueva línea) se trataran especialmente.zshtratamiento con cadena que contiene 2 o más caracteres${(s:string:)var}? Si se agrega, puedo eliminar mi respuesta :)Ssignifica Separador , no delimitador . Al menos, eso es lo que dice el manual de mi bash.$IFSproviene del shell Bourne donde estaba el separador , ksh cambió el comportamiento sin cambiar el nombre. Menciono eso para enfatizar quesplit+glob(excepto en zsh o pdksh) ya no se divide simplemente.Sí, utilícelo
IFSy configúrelo en_. Luego, useread -apara almacenar en una matriz (-rdesactiva la expansión de barra invertida). Tenga en cuenta que esto es específico de bash; ksh y zsh tienen características similares con una sintaxis ligeramente diferente, y sh simple no tiene variables de matriz en absoluto.De
man bash:Tenga en cuenta que se
readdetiene en la primera línea nueva. Pase-d ''areadpara evitar eso, pero en ese caso, habrá una nueva línea adicional al final debido al<<<operador. Puedes eliminarlo manualmente:fuente
$rque no contiene caracteres de nueva línea o barras invertidas. También tenga en cuenta que solo funcionará en versiones recientes delbashshell.bash,read -ase introdujo en bash 4, ¿verdad?<<<se agregó recientemente,bashpero parece que ha estado allí desde 2.05b (2002).read -aes incluso más viejo que eso.<<<provienezshy es compatible conksh93(y mksh y yash) también, peroread -aes específico de bash (está-Aen ksh93, yash y zsh).