- бесплатный, современный и кросс-платформенный редактор LaTeX для систем linux, macosx и windows, который объединяет множество инструментов, необходимых для разработки документов с помощью LaTeX, всего в одном приложении .
Texmaker включает поддержку Unicode, проверку орфографии, автозаполнение, сворачивание кода и встроенный просмотрщик PDF с поддержкой Synctex и непрерывным режимом просмотра. Texmaker прост в использовании и настраивается.
Texmaker выпущен под лицензией GPL.
Я взял на себя смелость немного изменить вашу функцию и поместить все в простой скрипт. Ядро проблемы заключается в том, что вам нужно было эхо после завершения цикла while. Кроме того, функции bash не возвращают массивы, вам нужно как-то отбросить их в stdout или использовать основную функцию и иметь основной массив local, который затем может быть доступен для дочерних функций (это то, что я делаю довольно часто в моих собственных скриптах).
Вот результат теста. Для 9 итераций, где столбец 1 всегда равен 110, мы получаем 990.
$ ./generate_lines.sh
990 1008 1035 1008 1017 1080
И вот сценарий:
#!/usr/bin/env bash
sum_line_tokens() {
while read line
do
#echo "$line"
logLine=$line # saves currently logged line in variable logLine
# redirect variable logLine as input for read command.
# read -a saves word of input string as array. InternalFieldSeparator set as ';'
# detects elements in input string which are separated by '; ' as words.
IFS=';' read -a arrayLog <<< $logLine
for n in 1 3 5 7 9 11
do
# define element in arraySum at position n as sum of previous element
# and element in arrayLog at this position
arraySum[n]=$(( ${arraySum[n]} + ${arrayLog[n]} ))
#echo "${arraySum[n]}"
done
done
# Functions in bash can only use return to indicate exit status
# This is more like int datatype for C or Java functions. If you want
# to return a string or array, you need to echo it to stdout
echo "${arraySum[@]}"
}
generate_lines(){
while [[ $i < 9 ]]
do
i=$(($i + 1))
echo "dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935"
done
}
generate_lines | sum_line_tokens
Пока скрипт работает, он длинный. Мы можем сократить решение с помощью awk:
# again, same thing - the script now generates lines only, no summing.
# We'll pipe it to awk
$ ./generate_lines.sh
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
$ ./generate_lines.sh | awk -F ';' '{for(i=1;i<=11;i++) if(i%2 != 0) sum[i+1]+=$(i+1) }END{for(j in sum) printf "%d\t",sum[j];print ""}'
990 1008 1035 1008 1017 1080
Я большой сторонник использования функций main в скриптах, потому что он держит все и в качестве дополнительного преимущества вы можете объявить локальную переменную, которую каждая функция, которую вы вызываете из main, будет знать и сможет перезаписать.
Ну, в вашей дело. У нас есть две функции: одна создает линии, а другая - делает что-то с этими строками, а использование труб имеет проблему - все, что работает на правой стороне канала, выполняется в подоболочке, а это означает, что вся информация из подоболочки исчезнет, когда подоболочка выходит , См. Мой старый вопрос для справки.
Поэтому нам нужна нейтральная земля - либо мы используем временный файл, либо что-то известное как «named pipe». В этом примере я просто использовал временный файл. Если вещь, которую нужно разобрать, не слишком велика, вы всегда можете хранить все в локальной переменной и позволить двум функциям иметь дело с той же самой переменной - одна запись в переменную, одна - разбор переменной. В случае длинного текста, который попадает в тысячи строк, лучше использовать некоторый временный файл.
Итак, в этой версии скрипта я рассмотрел несколько вещей, включая основную функцию и способ получения главной функции аргументы командной строки, а также то, что вы запросили в комментариях. В принципе, скрипт теперь получает 1 аргумент командной строки - это число строк, которое вы хотите, и даете это функции sum_line_tokens. Без аргументов командной строки он суммирует все строки.
Тестирование:
$ ./generate_lines.sh 3
330 336 345 336 339 360
$ ./generate_lines.sh 4
440 448 460 448 452 480
И сам скрипт:
#!/usr/bin/env bash
sum_line_tokens() {
# To perform counting for n number of lines, use a counter variable
# In this case I am using argument passed from command-line
linecount=0
# IFS= and -r for better line reading to ensure that spaces won't mess you up
while IFS='' read -r line
do
# Check if we have arg 1 to function and quit after n lines
if [ -n $1 ] && [ $linecount -eq $1 ]
then
break
fi
logLine=$line
IFS=';' read -a arrayLog <<< $logLine
for n in 1 3 5 7 9 11
do
arraySum[n]=$(( ${arraySum[n]} + ${arrayLog[n]} ))
done
# increment line counter
((linecount++))
done
}
generate_lines(){
while [[ $i < 9 ]]
do
i=$(($i + 1))
echo "dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935"
done
}
main(){
# create local array. Any function called from main will know about it
local -a arraySum
# We can't just pipe lines to summing function. Whatever runs on the right-hand side
# of the pipe runs in subshell, which means when that subshell exits, your variables are gone
# See https://askubuntu.com/q/704154/295286
tempfile=$(mktemp)
generate_lines > "$tempfile"
sum_line_tokens "$1" < "$tempfile"
echo "${arraySum[@]}"
rm "$tempfile"
}
# Call main function with the command-line arguments. This works sort of like int main(String[] args) in Java
main "$@"
Конечно, потому что мы используем много особых вещей, связанных с bash, если вы запускаете это в системе, где bash недоступен, это не сработает. Это хороший сценарий? Да, это делает работу. Этот переносимый сценарий? Нет. Решение awk выше, вероятно, более портативное.
Я взял на себя смелость немного изменить вашу функцию и поместить все в простой скрипт. Ядро проблемы заключается в том, что вам нужно было эхо после завершения цикла while. Кроме того, функции bash не возвращают массивы, вам нужно как-то отбросить их в stdout или использовать основную функцию и иметь основной массив local, который затем может быть доступен для дочерних функций (это то, что я делаю довольно часто в моих собственных скриптах).
Вот результат теста. Для 9 итераций, где столбец 1 всегда равен 110, мы получаем 990.
$ ./generate_lines.sh
990 1008 1035 1008 1017 1080
И вот сценарий:
#!/usr/bin/env bash
sum_line_tokens() {
while read line
do
#echo "$line"
logLine=$line # saves currently logged line in variable logLine
# redirect variable logLine as input for read command.
# read -a saves word of input string as array. InternalFieldSeparator set as ';'
# detects elements in input string which are separated by '; ' as words.
IFS=';' read -a arrayLog <<< $logLine
for n in 1 3 5 7 9 11
do
# define element in arraySum at position n as sum of previous element
# and element in arrayLog at this position
arraySum[n]=$(( ${arraySum[n]} + ${arrayLog[n]} ))
#echo "${arraySum[n]}"
done
done
# Functions in bash can only use return to indicate exit status
# This is more like int datatype for C or Java functions. If you want
# to return a string or array, you need to echo it to stdout
echo "${arraySum[@]}"
}
generate_lines(){
while [[ $i < 9 ]]
do
i=$(($i + 1))
echo "dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935"
done
}
generate_lines | sum_line_tokens
Пока скрипт работает, он длинный. Мы можем сократить решение с помощью awk:
# again, same thing - the script now generates lines only, no summing.
# We'll pipe it to awk
$ ./generate_lines.sh
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935
$ ./generate_lines.sh | awk -F ';' '{for(i=1;i<=11;i++) if(i%2 != 0) sum[i+1]+=$(i+1) }END{for(j in sum) printf "%d\t",sum[j];print ""}'
990 1008 1035 1008 1017 1080
Я большой сторонник использования функций main в скриптах, потому что он держит все и в качестве дополнительного преимущества вы можете объявить локальную переменную, которую каждая функция, которую вы вызываете из main, будет знать и сможет перезаписать.
Ну, в вашей дело. У нас есть две функции: одна создает линии, а другая - делает что-то с этими строками, а использование труб имеет проблему - все, что работает на правой стороне канала, выполняется в подоболочке, а это означает, что вся информация из подоболочки исчезнет, когда подоболочка выходит , См. Мой старый вопрос для справки.
Поэтому нам нужна нейтральная земля - либо мы используем временный файл, либо что-то известное как «named pipe». В этом примере я просто использовал временный файл. Если вещь, которую нужно разобрать, не слишком велика, вы всегда можете хранить все в локальной переменной и позволить двум функциям иметь дело с той же самой переменной - одна запись в переменную, одна - разбор переменной. В случае длинного текста, который попадает в тысячи строк, лучше использовать некоторый временный файл.
Итак, в этой версии скрипта я рассмотрел несколько вещей, включая основную функцию и способ получения главной функции аргументы командной строки, а также то, что вы запросили в комментариях. В принципе, скрипт теперь получает 1 аргумент командной строки - это число строк, которое вы хотите, и даете это функции sum_line_tokens. Без аргументов командной строки он суммирует все строки.
Тестирование:
$ ./generate_lines.sh 3
330 336 345 336 339 360
$ ./generate_lines.sh 4
440 448 460 448 452 480
И сам скрипт:
#!/usr/bin/env bash
sum_line_tokens() {
# To perform counting for n number of lines, use a counter variable
# In this case I am using argument passed from command-line
linecount=0
# IFS= and -r for better line reading to ensure that spaces won't mess you up
while IFS='' read -r line
do
# Check if we have arg 1 to function and quit after n lines
if [ -n $1 ] && [ $linecount -eq $1 ]
then
break
fi
logLine=$line
IFS=';' read -a arrayLog <<< $logLine
for n in 1 3 5 7 9 11
do
arraySum[n]=$(( ${arraySum[n]} + ${arrayLog[n]} ))
done
# increment line counter
((linecount++))
done
}
generate_lines(){
while [[ $i < 9 ]]
do
i=$(($i + 1))
echo "dateTime;110;2930;112;2931;115;2932;112;2933;113;2934;120;2935"
done
}
main(){
# create local array. Any function called from main will know about it
local -a arraySum
# We can't just pipe lines to summing function. Whatever runs on the right-hand side
# of the pipe runs in subshell, which means when that subshell exits, your variables are gone
# See https://askubuntu.com/q/704154/295286
tempfile=$(mktemp)
generate_lines > "$tempfile"
sum_line_tokens "$1" < "$tempfile"
echo "${arraySum[@]}"
rm "$tempfile"
}
# Call main function with the command-line arguments. This works sort of like int main(String[] args) in Java
main "$@"
Конечно, потому что мы используем много особых вещей, связанных с bash, если вы запускаете это в системе, где bash недоступен, это не сработает. Это хороший сценарий? Да, это делает работу. Этот переносимый сценарий? Нет. Решение awk выше, вероятно, более портативное.