Должна ли каждая группа процессов принадлежать к одному сеансу процесса?

Все примеры, представленные ниже, подходят для общего случая, когда в строке есть произвольное количество слов. Основная идея везде одна и та же - мы должны читать файл построчно и печатать слова в обратном порядке. AWK облегчает это лучше всего, потому что в нем уже есть все необходимые инструменты для программной обработки текста, и он наиболее переносим - его можно использовать с любой производной от awk, и в большинстве систем они есть. В Python также есть несколько хороших утилит для обработки строк, которые позволяют нам выполнять эту работу. Я бы сказал, что это инструмент для более современных систем. Bash, IMHO, является наименее желательным подходом из-за переносимости, потенциальных опасностей и количества "уловок", которые необходимо сделать.

AWK

$ 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:

$ 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 () создает строку еще большего размера, при этом каждый элемент присоединяется через новую строку.

Короче говоря, этот метод представляет собой подход «разорвать и перестроить».

BASH

#!/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 

Дополнительно: perl и ruby ​​

Та же идея, что и с 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
1
20.12.2016, 20:04
1 ответ

POSIX определяет сеансов таким образом:

Набор групп процессов, созданных для управления заданиями. Каждая группа процессов является членом сеанса. Процесс считается членом сеанса, членом которого является его группа процессов. Вновь созданный процесс присоединяется к сеансу его создателя. Процесс может изменять свое членство в сеансе; см. setsid () . В одном сеансе может быть несколько групп процессов.

Все группы процессов принадлежат сеансу.Однако концепции не зависят друг от друга, поэтому я бы не сказал, что группа процессов - это концепция , которая существует только в рамках сеанса.

Фоновым процессам при создании предоставляется их собственная группа процессов, поэтому отказ от них не меняет их группу процессов; disown управляет только таблицей заданий Bash :

disown [ -ar ] [ -h ] [ jobspec ] ...]

Без параметров удалите все спецификации из таблицы активных заданий. Если спецификация задания отсутствует и не указаны ни -a , ни -r параметр, используется текущее задание. Если задана опция -h , каждая спецификация задания не удаляется из таблицы, а помечается так, что SIGHUP не отправляется на задание, если оболочка получает SIGHUP . Если спецификация задания не указана, параметр -a означает удаление или отметку всех заданий; параметр -r без Аргумент jobspec ограничивает операцию выполняемыми заданиями. Возвращаемое значение - 0 , если в спецификации задания не указано допустимое задание.

3
27.01.2020, 23:25

Теги

Похожие вопросы