Programando For Todos 2
Programando For Todos 2
In this article, I am going to demonstrate batch processing using one of the projects of Spring
which is Spring Batch. Spring Batch provides functions for processing large volumes of data
in batch jobs. This includes logging, transaction management, job restart (if a job is not
completed), job skip, job processing statistics, and resource management.
A step is an object that encapsulates sequential phase of a job and holds all the necessary
information to define and control processing. It delegates all the information to a Job to carry
out its task.
Spring Batch uses chunk oriented style of processing which is reading data one at a time, and
creating chunks that will be written out within a transaction. The item is read by ItemReader
and passed onto ItemProcessor, then it is written out by ItemWriter once the item is ready.
The Job Repository will be used to store the step execution periodically during the item
processing.
In this article, I will be using sample data which represents voltage drop for a discharging
Capacitor. We will read this data from a CSV file and write it out to an in-memory database
which is H2.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
The CSV file Volts.csv contains two fields volt and time. Let us create a JPA entity called
Voltage. Note that this entity is just for the example. It is not production ready code.
Batch configuration
Let’s create a batch configuration class:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
}
@Autowired
public JobBuilderFactory jobBuilderFactory; @Autowired
public StepBuilderFactory stepBuilderFactory;
JobBuilderFactory creates a job builder. Using StepBuilderFactory, Spring Batch will create
a step builder and will initialize its job repository and transaction manager.
Configuring ItemReader
We will now define ItemReader interface for our model Voltage which will be used for
reading data from CSV file.
@Bean
public FlatFileItemReader<Voltage> reader() {
return new FlatFileItemReaderBuilder<Voltage>()
.name("voltItemReader")
.resource(new ClassPathResource("Volts.csv"))
.delimited()
.names(new String[]{"volt", "time"})
.lineMapper(lineMapper())
.fieldSetMapper(new BeanWrapperFieldSetMapper<Voltage>() {{
setTargetType(Voltage.class);
}})
.build();
}
@Bean
public LineMapper<Voltage> lineMapper() { final DefaultLineMapper<Voltage>
defaultLineMapper = new DefaultLineMapper<>();
final DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setDelimiter(";");
lineTokenizer.setStrict(false);
lineTokenizer.setNames(new String[] {"volt","time"}); final VoltageFieldSetMapper
fieldSetMapper = new VoltageFieldSetMapper();
defaultLineMapper.setLineTokenizer(lineTokenizer);
defaultLineMapper.setFieldSetMapper(fieldSetMapper); return defaultLineMapper;
}
In the custom lineMapper, we can specify the delimiter to be read from CSV file and also
used for reading string values into database specific datatypes. The VoltageFieldSetMapper is
defined as follows:
Configuring ItemProcessor
@Bean
public VoltageProcessor processor() {
return new VoltageProcessor();
}
We have defined a custom processor VoltageProcessor. Once the data is read, this processor is
used for processing the data such as data conversion, applying business logic and so on. This
is just an example. This custom processor may not always be required. It can be defined
depending on your application requirements.
package com.techshard.batch.configuration;import
com.techshard.batch.dao.entity.Voltage;import
org.springframework.batch.item.ItemProcessor;import java.math.BigDecimal;public class
VoltageProcessor implements ItemProcessor<Voltage, Voltage>{ @Override
public Voltage process(final Voltage voltage) {
final BigDecimal volt = voltage.getVolt();
final double time = voltage.getTime(); final Voltage processedVoltage = new
Voltage();
processedVoltage.setVolt(volt);
processedVoltage.setTime(time);
return processedVoltage;
}
}
ItemWriter
Once the data is processed, the data needs to be stored in database as per our requirement. We
will define a JdbcBatchWriter to insert data into database table. There is also JPA specific
JpaItemWriter which can be used with EntityManager.
@Bean
public JdbcBatchItemWriter<Voltage> writer(final DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Voltage>()
.itemSqlParameterSourceProvider(new
BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO voltage (volt, time) VALUES (:volt, :time)")
.dataSource(dataSource)
.build();
}
We will now define a Step which will contain a reader, processor, and writer in the same way
we need a StepBuilderFactory, which will be used to inject in our Job() method.
@Bean
public Step step1(JdbcBatchItemWriter<Voltage> writer) {
return stepBuilderFactory.get("step1")
.<Voltage, Voltage> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer)
.build();
}
Here, step1 is just a name of the Step which we can define. We can also specify chunk size in
Step configuration.
@Bean
public Job importVoltageJob(NotificationListener listener, Step step1) {
return jobBuilderFactory.get("importVoltageJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
Note that we have passed NotificationListener that extends Spring Batch’s
JobExecutionListenerSupport. It can log results before or after job execution. Here, we have
only defined afterJob(). JobExecutionListenerSupport also provides beforeJob() to log any
information before the job execution.
package com.techshard.batch.configuration;
import com.techshard.batch.dao.entity.Voltage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class NotificationListener extends JobExecutionListenerSupport{
@Autowired
public NotificationListener(final JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void afterJob(final JobExecution jobExecution) {
if(jobExecution.getStatus() == BatchStatus.COMPLETED) {
LOGGER.info("!!! JOB FINISHED! Time to verify the results");
spring.datasource.url=jdbc:h2:mem:batchdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
Additionally, I have also configured Aspect using Spring AOP to measure the time taken by
batch execution.
package com.techshard.batch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TracePerformanceAspect {
return result;
}
}
Run the Spring Boot application. Once the application is started, login to H2 console using
link http://localhost:8080/h2-console/ . Then, you will get a login screen as below.
H2 Console Login screen
Once we login, we will be able to see the table Voltage and all the tables created by Spring
Batch. In these tables, we will find all the details about job execution such as job name,
status, id and so on.
H2 Database
Conclusion
This article just scratched the surface of Spring Batch in general. The example used in this
article is not production ready code. You can define job configuration depending on your
project requirements. I hope you enjoyed this article. Let me know if you have any comments
or suggestions.
https://github.com/swathisprasad/batch-processing-large-datasets-spring
https://techshard.com/2019/07/22/batch-processing-large-data-sets-with-spring-boot-and-
spring-batch/
Now we tend to go more towards automated systems that are composed of several elements
designed to perform a set of scheduled tasks. They simplify, secure and make repetitive and
operational tasks easier. These processes are complex and with large volumes of information
without human interaction(read a file, process data, export data to a database, etc.).
Imagine our application receive every hour , from a file, a set of users informations from a
file to process, generate a password for every user in the file and insert it in a database.
In my mind I thought to make a shell script or develop a program from scratch to do the
process (recover, loop, read, process, transform, insert, …). But within this mode of treatment
the risk is enormous. This may take longer, error handling is to be expected, manage
rollbacks , not reliable because of the possibility of having an OutOfMemoryError, … I was
not ready to reinvent the wheel( Don’t Repeat Yourself they said). Thus, i started looking for
solutions in Internet and suddenly i come across a framework that allows to repeat a
treatment on a set of large volumes of data without human intervention. It was Spring Batch
and for me it was also the opportunity to test Spring and its ecosystem. Let’s go!
Spring batch ???
Spring Batch is a lightweight, comprehensive batch framework designed to enable the
development of robust batch applications vital for the daily operations of enterprise systems.
Spring Batch is not a scheduling framework. It provides reusable functions that are essential
in processing large volumes of records, including logging/tracing, transaction management,
job processing statistics, job restart, skip, and resource management.
Key Concepts
See the Batch Domain for more details.
• Job : A batch job composed of a sequence of one or more Steps.
• JobInstance :an instance of a Job configured with parameters (requested, for a
specific date for example). A collection of JobExecutions.
• Step : An independent, discrete unit of work in a Job. A simple Step might load data
from a file into the database, but may be more complex.
• JobExecution : An single attempt of a Job run (may be in progress, succeeded, or
failed)
• StepExecution : A single attempt of a Step, associated with a JobExecution (may be
in progress, succeeded or failed)
• JobRepository : Persistent storage for maintaining the Batch Domain model and
associated state
• JobExecutionListener : Extension point for customizing JobExecution events.
• StepExecutionLister : Extension point for customizing StepExecution events.
• Remote Chunking, Partitioning* : Patterns for scalable distributed batch processing,
see the docs for details.
•Among others we can see as advantages
• Less coding
• More unit tests & integrations
• He takes care of the increase in load
• And many others ( see HERE)
1 — At the end of the month, the company must send a salary to the respective accounts of
its employees.
Technical Objectives
As a developer also we see a considerable contribution in our work with the use of spring
batch.
Batch developers use the Spring programming model: concentrate on business logic and let
the framework take care of infrastructure.
Clear separation of concerns between the infrastructure, the batch execution environment,
and the batch application.
Easy to configure, customize, and extend services, by leveraging the spring framework in
all layers.
All existing core services should be easy to replace or extend, without any impact to the
infrastructure layer.
Provide a simple deployment model, with the architecture JARs completely separate from
the application
This layered architecture highlights three major high-level components: Application, Core,
and Infrastructure.
Application
The application contains all batch jobs and custom code written by developers using Spring
Batch.
Code
The Batch Core contains the core runtime classes necessary to launch and control a batch job.
It includes implementations for JobLauncher, Job, and Step.
Infrastructure
This infrastructure contains common readers and writers and services (such as the
RetryTemplate), which are used both by application developers(readers and writers, such as
ItemReader and ItemWriter) and the core framework itself (retry, which is its own library).
Sample example
Here is a quick overview of how we plan to process our received files from .
1- At first, data is read from a file using the ItemReader that is part of Spring Batch.
2- The data is then passed to the processor (ItemProcessor) for processing the data according
to the needs of the enterprise. We have to format the date to adapt it to the database.
3- The processed data that is now modified is transmitted in the database for writing
(ItemWritter).
Skip non-blocking errors (skip). Sometimes we do not need to stop stuff if we encounter
some errors.
Start a job again (retry). The database may be unavailable at a temporary moment.
Sometimes we need to retry the process.
Restart a batch (restart). After an error we are able to restart it.
Demo
For example i set up a small application that allows us to recover data from a file, do certain
treatments before inserting it into a database. Using Spring Batch Flat file reader to read CSV
file and Jdbc Batch Item Writer to write MySQL Database. After the treatment we can do
other actions depending on the result of the job. If job success we can send a notification
mail. If not we can retry to lunch the job or do something else.
INPUT
OUTPUT
https://github.com/tonux/file-processor
https://medium.com/@ndongotonuxsamb/introduction-to-spring-batch-41b5e11fd5f5
Linux Shell
Esto comúnmente es lo que se le llama en los Sistemas Operativos, La Consola. Con las
versiones nuevas de Microsoft Windows se ha dejado un poco atrás, con esto de que hay
asistentes, gráficos para facilitar el trabajo al usuario, pero cuando no existía estas cosas,
antaño se usaba lo que es el Intérprete de Comandos. Básicamente es el infierno de los
usuarios de interfaces gráficos, pero en realidad de esta forma tienes más control y más
opciones de configuración. Que sí, que es más feo, todo en texto plano, pero no deja de ser
eficiente, efectivo y lo mejor de todo, apenas consume memoria ya que no usa gráfico
alguno.
¿Que es Shell?
Básicamente un script de shell es un archivo de texto simple con listas de comandos que se
ejecutan de forma secuencial. Se compone de procedimientos, variables, funciones,
condiciones, bucles, arrays…etc, como cualquier otro lenguaje de programación, pero
orientado a la consola de un sistema operativo. Existen diferentes tipos de interpretes:
• Bourne Shell o sh. Se creó en 1977 y se convirtió en el intérprete por defecto en las
primeras versiones de UNIX.
• Korn Shell. Se creó a principios de los 80 para el proyecto GNU.
• Bash. Se creo en 1987 también para el proyecto GNU. Muchas ideas fueron basadas
del Korn Shell. Actualmente es el principal intérprete en las mayoría de las
distribuciones Linux que hay en la actualidad.
• Zsh. Se creó en 1990. En principio se diseñó para poder usarlo de forma interactiva.
• Todos son buenos intérpretes para usar, algunos con sus pros y sus contras, pero yo
me voy a centrar un poco en bash, que es el que se usa comúnmente en las
distribuciones Linux más usadas.
• Información de Shell.
• echo $SHELL # Indica el shell que estamos usando.
echo $BASH_VERSION #Indica la versión de shell bash.
whereis bash # Indica donde está instalado shell bash.
cat /etc/shells # Indica todos los shell que hay
instalado.
chsh -s /bin/bash # Poner por defecto shell bash.
En esta parte vamos hablar de los distintos operadores que existen en la programación;
ariméticos, lógicos, booleanos, string y los file test.
Aritméticos.
• +. Asignación.
• -. Substracción.
• *. Multiplicación.
• /. División
• %. Módulo o resto de una división.
• =. Asignación.
• ==. Comparación de números.
• !=. Negación.
• Algunos ejemplos:
• valor=`expr $a + $b`
valor`expr $a — $b`
valor `expr $a \* $b`
[ $a == $b ]
• Hay que tener en cuenta una cosa, Shell es un poco especial y debemos separar
siempre los operadores de las variables o dará un error;
• ¿Que es eso de expr?. Se utiliza para guardar el resultado de una expresión en una
variable.
• Relacionales.
• Este tipo de operadores se utilizan sólo y exclusivamente para cadena de carácteres.
• -eq. Compara si son iguales dos cadenas. Si lo son devuelve un true.
• -ne. Compara si son iguales dos cadenas. Si no lo son devuelve un true.
• -gt. Compara si la cadena de la izquierda es mayor que el de la derecha. Si es así
devuelve un true.
• -lt. Compara si la cadena de la izquierda es menor que el de la derecha. Si es así
devuelve un true.
• -ge. Compara si la cadena de la izquierda es mayor o igual que el de la derecha. Si es
así devuelve un true.
• -le. Compara si la cadena de la izquierda es menor o igual que el de la derecha. Si es
así devolverá un true.
• Booleanos.
• !. Niega una comparación.
• -o. Se utiliza para condiciones compuestas. Si una de las dos se cumple devuelve un
verdadero. [ $a -lt 20 -o $b -gt 100 ] .
• -a. Se utiliza para condiciones compuestas. Si se cumplen las dos condiciones a la vez
devuelve un true. [ $a -lt 20 -a $b -gt 100 ].
• String.
• =. Compara los valores y si son iguales devuelve un true.
• !=. Compara los valores y si es lo contrario que la expresión devuelve un true.
• -z. Compara si la longitud del valor es 0 y si lo es devuelve un true.
• -n. Compara si la longitud del valor es distinta de 0. Si es así devuelve un true.
• str. Compara si la cadena está vacia, si no está vacia devuelve un true.
• Files.
• Este tipo de operadores sirve para saber las propiedades dadas a un archivo en Linux,
es decir, los permisos de lectura, escritura y ejecución.
• -b file. Establece si el archivo es referente a un dispositivo del sistema, es decir,
perteneciente a /dev.
• -c file. Archivos especiales de tipo carácter.
• -d file. Que sea un directorio o carpeta.
• -f file. Que sea un archivo ordinario, es decir, que no sea ni un directorio ni archivo
especial.
• -g file. Comprueba que tenga activo el SGID, es decir, todo archivo que tenga activo
el SGID, al ser ejecutado, tendrá los privilegios del grupo al que pertenece.
• -k file Comprueba si tiene activo el sticky bit.¿Esto que es?. Cuando este bit está
activo, hace que un usuario sólo pueda borrar los ficheros que son de su propiedad en
dicho directorio.
• -p file Comprueba que el archivo sea named pipe.
• -t file Comprueba si el descriptor de archivo está abierto y asociado a una terminal.
• -u file. Comprueba si el archivo tiene establecido su SUID. El bit SUID activo en un
archivo significa que el que lo ejecute va a tener los mismos permisos que el que creó
el archivo
• -r file. Comprueba que el archivo tenga permisos de lectura.
• -w file. Comprueba que el archivo tenga permisos de escritura.
• -x file. Comprueba que el archivo tenga permisos de ejecución.
• -s file Comprueba que el archivo tiene un tamaño mayor de 0.
• -e file Comprueba que el archivo existe. En el caso que sea un directorio el sistema lo
dará por válido.
Las condiciones son algo muy esencial en cualquier lenguaje de programación, dependiendo
de lo que pase a lo largo de un procedimiento, escogeremos un camino u otro. Veamos como
funciona:
if [ expression ]
then
instrucciones
fi
Cuando se cumple y no se cumple:
if [ expression ]
then
instrucciones cuando se cumple la condición.
else
instrucciones cuando no se cumple la condición
fi
Cuando son muchos if…else anidados:
if [ expression 1 ]
then
instrucciones
elif [ expression 2 ]
then
instrucciones
elif [ expression 3 ]
then
instrucciones
else
instrucciones
fi
Bucles.
Los bucles es una instrucción también muy usada e importante en la programación, ya que
permite crear bucles de instrucciones tantas veces como nos haga falta y así evitar repetir
mucho código.
While.
Este tipo de bucle hace las instrucciones que vienen dentro hasta que no se cumpla la
condicíon, es decir, lo va hacer mientras que la condición se cumpla. Veamos como funciona:
while command
do
instrucciones
done
Un ejemplo:
#!/bin/bash
a=0
while [ $a -lt 12 ]
do
echo “El valor de a es: $a”
a=`expr $a + 1`
done
En este ejemplo hacemos el bucle hasta que sea mayor de 11 o 12 y muestra el valor de a. Es
decir, el resultado será algo así; 0 1 2 3 4 5 6 7 8 9 10 11 y en el 12 sale del bucle.
FOR.
El bucle for funciona en listas de elementos. Repite un conjunto de instrucciones para cada
elemento en una lista.
for var in elemento1 elemento2 ... elementoN
do
instrucciones por cada elemento
done
Un ejemplo:
#!/bin/bash
for var in 0 1 2 3 4 5 6 7 8 9
do
echo $var
done
¿y que pasaría si fueran 300 elementos? Sería un poco pesado poner 300 elementos en el for.
Para evitar eso podemos usar la instrucción seq:
#!/bin/bashfor var in $(seq 0 9)
do
echo $var
done
Until loop.
Este tipo de bucle se usa cuando queramos que haga el bucle mientras las condición no se
cumpla. Veamos como se usa:
until command
do
instrucciones
done
Veamos un ejemplo:
#!/bin/bash
a=0
until [ ! $a -lt 12 ]
do
echo $a
a=`expr $a + 1`
done
El bucle lo va a hacer mientras que no se cumpla la condición, es decir, negar que a sea
menor de 12 quiere decir que es mayor o igual de 12. Como a no es mayor e igual de 12, hace
instrucciones que hay dentro. El bucle se acabará cuando sea 12.
Select.
Este tipo de bucle proporciona una manera fácil de crear un menú numerado desde el cual los
usuarios pueden seleccionar opciones. Veamos como funciona:
select var in opcion1 opcion2... opcionN
do
instrucciones
done
Veamos un ejemplo:
#!/bin/bash
a=0
while [ $a -lt 10 ]
do
echo $a
if [ $a -eq 5 ]
then
break
fi
a=`expr $a + 1`
done
echo “El bucle ha terminado en la posición $a”
En este ejemplo vamos hacer un bucle del 0 al 10. Pero cuando llega a 5 mediante la
condición, hace un break y se sale de bucle y echa la siguiente línea de código después de
bucle.
Continue. Esta instrucción funciona muy parecida a break, la diferencia está que no rompe el
bucle entero, si no la iteración y pasa a la siguiente en el bucle. Veamos un ejemplo:
#!/bin/bash
NUMS="1 2 3 4 5 6 7"
El shell realiza una sustitución cuando encuentra una expresión que contiene uno o más
caracteres especiales. Veamos un ejemplo:
#!/bin/basha=10
echo -e "Value of a is $a \n"
En este ejemplo, simplemente mostramos el valor de a.
La opción -e sirve para que nos de la interpretación de los caracteres espaciales que hay en la
barra invertida (\n).
• \n. Nueva línea.
• \\. Muestra el carácter de barra invertida como texto.
• \a. Muestra un pitido de alerta.
• \b. Retroceso.
• \c. Suprime línea nueva.
• \r. Retorno de carro.
• \t. Pestaña horizontal.
• \v. Pesteña vertical.
• Shell también nos permite guardar el resultado de la ejecución de comandos,
simplemente metiendo el comando entre comillas inversas:
• #!/bin/bashDATE=`date`
echo "Date is $DATE"#Incluso varios comandos a la vez
separados por comas.
UP=`date ; uptime`
echo "Uptime is $UP"
• Sustitución de Variables.
• La sustitución de variables permite al usuario poder modificar el contenido de éstas
según su estado:
• ${variable}. Sustituye el valor de variable.
• ${variable:-”mensaje”}. Si la variable es nula o no tiene valor, lo sustituirá por
“mensaje”, pero en ningún caso modificará el valor de variable. Se suele utilizar para
mensajes de errores.
• ${variable:=”mensaje”}. Si la variable es nula o no tiene valor, se guardará por
defecto el valor que pongamos después del igual.
• ${variable:?menaje}. Si la variable es nula o no tiene valor, se imprirá lo que
pongamos después de la interrogación.
• ${variable:+palabra}. Si la variable se establece, es sustituido por palabra pero el
valor de variable no se modificará en ningún caso.
• #!/bin/bashvar=1echo ${var:-"No tiene valor"}
echo "1 - El valor es ${var}"echo ${var:="No tiene
valor"}
echo "2 - valor es ${var}"unset var
echo ${var:+"Por Defecto"}
echo "3 - El valor es $var"var="Otro valor"
echo ${var:+"Tiene valor"}
echo "4 - El valor es $var"echo ${var:?"Muéstrame este
mensaje"}
echo "5 - El valor es ${var}"
• Si no tuviera valor mostraría “No tiene valor”
• Si no tuviera valor guardaría en la variable “No tiene valor”.
• Si no tuviera valor o no existiera guardaría en la variable “Por Defecto”
• Si tiene valor mostraría el mensaje “Tiene valor”.
• Si no tiene valor o no existe mostraría el mensaje “Muéstrame este mensaje”.
• Metacaracteres.
• Shell proporciona varios caracteres que tienen un significado especial al usarlos en
cualquier Script, es decir, son como reservados por el propio sistema para realizar
ciertas funciones especiales.
• Un ejemplo claro puede ser el signo ? . Se utiliza para referirnos a un sólo carácter
cuando se listan archivos o se busca por algún patrón. También le pasa al signo *, que
lo utilizamos para referirnos a una cantidad indeterminada de caracteres a la hora de
buscar o listar archivos.
• Aquí hay una lista de la mayoría de los caracteres:
• * ? [ ] ' " \ $ ; & ( ) | ^ < > new-line space tab
• Algunos ejemplos:
• #!/bin/sh
Las funciones funcionan exactamente igual que los script, la diferencia está en que lo puedes
llamar desde cualquier lugar, ya que se cargan directamente en el entorno del intérpretes de
comandos. Son muy similares a las subrutinas, procedimientos y funciones en otros lenguajes
de programación. Su sintáxis básica es la siguiente;
function nombre_funcion() {
lista de comandos
}
Vamos con un ejemplo muy básico para ver como funciona.
#!/bin/bash# Creamos la función.
function hola() {
echo "Hola Ismael, este es mi primer ejercicio de funciones"
}
A la hora de llamar al procediendo
#Llamamos al procedimiento con el nombre de la función
hola
Las funciones son muy eficientes a la hora de trabajar, ya que podemos usarlas en cualquier
momento, en cualquier lugar, la única pega que tiene es que se deben cargar en memoria
todas las funciones para usar esa ventaja. Aunque en la actualidad con la cantidad de
memoria que usan los ordenadores, no debería preocuparnos, pero bueno, por eficacia y
eficiencia no deberíamos malgastar memoria aunque sea mucha cantidad. Para ver todas las
funciones que tenemos en el entorno del intérprete de comandos se ejecuta:
declare -F
Si queremos borrar una función del entorno de trabajo ejecutamos lo siguiente:
unset -f nombre_funcion
Para definir una función sólo basta escribirla directamente en la consola o mediante un script,
de forma que cuando se ejecute se carga en memoria.
Las funciones también pueden devolver valores con la instrucción “return”, veamos un
ejemplo:
#!/bin/bash
# Definimos la función
function hola () {
echo "Hola $1"
return 25
}
URL author
https://medium.com/@benezor79