Все примеры, представленные ниже, подходят для общего случая, когда в строке есть произвольное количество слов. Основная идея везде одна и та же - мы должны читать файл построчно и печатать слова в обратном порядке. AWK облегчает это лучше всего, потому что в нем уже есть все необходимые инструменты для программной обработки текста, и он наиболее переносим - его можно использовать с любой производной от awk, и в большинстве систем они есть. В Python также есть несколько хороших утилит для обработки строк, которые позволяют нам выполнять эту работу. Я бы сказал, что это инструмент для более современных систем. Bash, IMHO, является наименее желательным подходом из-за переносимости, потенциальных опасностей и количества "уловок", которые необходимо сделать.
$ awk '{for(i=NF;i>=1;i--) printf "%s ", $i;print ""}' input.txt
Earth Hello
Mars Hello
Это работает довольно просто: мы перебираем в обратном направлении каждое слово в строке, печатаем слова, разделенные пробелом - это делается с помощью printf "% s", $ i
функция (для печати форматированных строк) и for-loop. Переменная NF
соответствует количеству полей. Предполагается, что разделителем полей по умолчанию является пробел. Мы начинаем с установки переменной выброса i
на количество слов и на каждой итерации уменьшаем значение переменной. Таким образом, если в строке 3 слова, мы печатаем поле $ 3, затем $ 2 и $ 1. После последнего прохода переменная i становится равной 0, условие i> = 1
становится ложным, и цикл завершается. Чтобы строки не сращивались, мы вставляем новую строку, используя print ""
.Блоки кода AWK {}
обрабатываются для каждой строки в этом случае (если есть условие соответствия перед блоком кода, это зависит от совпадения для блока кода, который должен быть выполнен или нет).
Для тех, кто любит альтернативные решения, вот python:
$ python -c "import sys;print '\n'.join([ ' '.join(line.split()[::-1]) for line in sys.stdin ])" < input.txt
Earth Hello
Mars Hello
Идея здесь немного другая. Оператор <
указывает вашей текущей оболочке перенаправить input.txt
в поток Python stdin
, и мы читаем этот построчный. Здесь мы используем понимание списка для создания списка строк - это то, что делает часть ['' .join (line.split () [:: - 1]) для строки в sys.stdin]
. Часть '' .join (line.split () [:: - 1])
берет строку, разбивает ее на список слов, переворачивает список через [:: - 1]
, а затем '' .join ()
создает из него строку, разделенную пробелами. В результате у нас есть список более крупных строк. Наконец, '\ n'.join ()
создает строку еще большего размера, при этом каждый элемент присоединяется через новую строку.
Короче говоря, этот метод представляет собой подход «разорвать и перестроить».
#!/bin/bash
while IFS= read -r line
do
bash -c 'i=$#; while [ $i -gt 0 ];do printf "%s " ${!i}; i=$(($i-1)); done' sh $line
echo
done < input.txt
И тестовый запуск:
$ ./reverse_words.sh
Earth Hello
Mars Hello
Сам Bash не обладает сильными возможностями обработки текста. Здесь происходит то, что мы читаем файл построчно через
while IFS= read -r line
do
# some code
done < text.txt
. Это частый метод и широко используется в сценариях оболочки для построчного чтения вывода команды или текстового файла. Каждая строка сохраняется в переменной $ line
.
Внутри у нас есть
bash -c 'i=$#; while [ $i -gt 0 ];do printf "%s " ${!i}; i=$(($i-1)); done' sh $line
Здесь мы используем bash
с флагом -c
для выполнения набора команд, заключенных в одинарные кавычки.Когда используется -c
, bash
начнет назначать аргументы командной строки переменным, начиная с $ 0
. Поскольку этот $ 0
традиционно используется для обозначения имени программы, я сначала использую фиктивную переменную sh
.
Некотируемая строка $
будет разбита на отдельные элементы из-за поведения, известного как разделение слов. Разделение слов часто нежелательно при написании сценариев оболочки, и вы часто слышите, как люди говорят: «Всегда указывайте переменные в кавычках, например,« $ foo »». Однако в этом случае для обработки простого текста желательно разделение слов. Если ваш текст содержит что-то вроде $ var
, это может нарушить этот подход. По этой и нескольким другим причинам я бы сказал, что подходы python и awk лучше.
Что касается внутреннего кода, он также прост: некотируемая $ строка
разбивается на слова и передается внутреннему коду для обработки. Мы берем количество аргументов $ #
, сохраняем его в переменной выброса i
и снова распечатываем каждый элемент, используя нечто, известное как косвенное обращение к переменной - это $ {! i}
часть (обратите внимание, что это bashism - она недоступна в других оболочках). И снова мы используем printf "% s"
для вывода каждого слова через пробел. Как только это будет сделано, echo
добавит новую строку.
По сути, этот подход представляет собой смесь awk и python. Мы читаем файл построчно, но разделяем и захватываем каждую строку, используя для этого несколько функций bash
.
Более простой вариант можно сделать с помощью команды GNU tac
и снова поиграть с разбиением слов. tac
используется для переворота строк входного потока или файла,но в этом случае мы указываем -s ""
, чтобы использовать пробел в качестве разделителя. Таким образом, var
будет содержать список слов, разделенных новой строкой, в обратном порядке, но из-за того, что $ var
не цитируется, новая строка будет заменена пробелом. Уловка, и опять же не самый надежный, но работает.
#!/bin/bash
while IFS= read -r line
do
var=$(tac -s " " <<< "$line" )
echo $var
done < input.txt
А вот 3 метода с произвольными строками ввода
$ cat input.txt
Hello Earth end of line
Hello Mars another end of line
abra cadabra magic
$ ./reverse_words.sh
line of end Earth Hello
line of end another Mars Hello
magic cadabra abra
$ python -c "import sys;print '\n'.join([ ' '.join(line.split()[::-1]) for line in sys.stdin ])" < input.txt
line of end Earth Hello
line of end another Mars Hello
magic cadabra abra
$ awk '{for(i=NF;i>=1;i--) printf "%s ", $i;print ""}' input.txt
line of end Earth Hello
line of end another Mars Hello
magic cadabra abra
Та же идея, что и с python - мы разбиваем каждую строку на массив слов, меняем массив и Распечатай.
$ perl -lane '@r=reverse(@F); print "@r"' input.txt
line of end Earth Hello
line of end another Mars Hello
magic cadabra abra
$ ruby -ne 'puts $_.chomp.split().reverse.join(" ")' < input.txt
line of end Earth Hello
line of end another Mars Hello
magic cadabra abra
POSIX определяет сеансов таким образом:
Набор групп процессов, созданных для управления заданиями. Каждая группа процессов является членом сеанса. Процесс считается членом сеанса, членом которого является его группа процессов. Вновь созданный процесс присоединяется к сеансу его создателя. Процесс может изменять свое членство в сеансе; см. setsid () . В одном сеансе может быть несколько групп процессов.
Все группы процессов принадлежат сеансу.Однако концепции не зависят друг от друга, поэтому я бы не сказал, что группа процессов - это концепция , которая существует только в рамках сеанса.
Фоновым процессам при создании предоставляется их собственная группа процессов, поэтому отказ от них
не меняет их группу процессов; disown
управляет только таблицей заданий Bash :
disown
[-ar
] [-h
] [ jobspec ] ...]Без параметров удалите все спецификации из таблицы активных заданий. Если спецификация задания отсутствует и не указаны ни
-a
, ни-r
параметр, используется текущее задание. Если задана опция-h
, каждая спецификация задания не удаляется из таблицы, а помечается так, чтоSIGHUP
не отправляется на задание, если оболочка получаетSIGHUP
. Если спецификация задания не указана, параметр-a
означает удаление или отметку всех заданий; параметр-r
без Аргумент jobspec ограничивает операцию выполняемыми заданиями. Возвращаемое значение - 0 , если в спецификации задания не указано допустимое задание.