Нужно некоторое sed волшебство: Перемещение отмеченных строк к началу файла

Если Вы хотите Redhat без Fedora использования стоимости лицензии, Научного Linux или CentOS. Fedora от Redhat, тогда как Научный и CentOS клоны Redhat.

CentOS ближе к Redhat, его основной целью является совместимость на уровне двоичных кодов.

OpenSource не запрещает это, Вы оплачиваете (патч) поддержку распределения.

5
10.11.2013, 21:44
7 ответов

действительно ли sed важен? если Вы не возражаете два, проходит через исходный файл, это легко сделано с grep.

например.

grep '^\*' input > outputfile
grep -v '^\*' input >> outputfile
10
27.01.2020, 20:31

Вам не нужно sed чтобы сделать это, можно использовать некоторые основные власти для получения по запросу звезды (*) строки к вершине. Скажите, например, что у Вас был этот файл:

$ cat sample.txt 
1
2
3
4
* 5
* 6
* 7
8
9
10

Теперь к grep файл sample.txt, помещая звезду (*) строки сначала:

$ cat <(grep '*' sample.txt) <(grep -v '*' sample.txt)
* 5
* 6
* 7
1
2
3
4
8
9
10

Вышеупомянутое выполнит 2 власти, 1-е получения по запросу все строки со звездами, в то время как 2-е получения по запросу все незвездообразные строки. Вывод от этих 2 команд перенаправляется, как введено к cat команда с помощью <() нотация.

Альтернативный метод

Если Вы не хотите использовать кошку + 2 подоболочки, можно сделать, как был предложен @terdon:

$ grep '*' sample.txt; grep -v '*' sample.txt

Это вытащит все строки из sample.txt это включает звезду (*) сопровождаемый всеми строками, которые не делают.

Ссылки

6
27.01.2020, 20:31
  • 1
    OP, вероятно, не хотел их файл, отсортированный... –  sendmoreinfo 28.06.2013, 08:10
  • 2
    @sendmoreinfo - спасибо не видело, что бит в вопросе, будет корректироваться. –  slm♦ 28.06.2013, 08:12
  • 3
    Почему Вы используете cat и подоболочки? grep '*' sample.txt;grep -v '*' sample.txt сделает точно то же самое. Я пропускаю что-то? –  terdon♦ 28.06.2013, 16:38
  • 4
    @terdon - Никакая причина просто не испытывала желание делать его тот путь. –  slm♦ 28.06.2013, 16:42
  • 5
    Вы не должны использовать cat. Это работает также: tac <(grep '*' sample.txt) <(grep -v '*' sample.txt) > >(tac). –   28.06.2013, 17:10

Если Вы не возражаете против пустой строки между этими двумя блоками:

sed -n -e '/^* /{H;$!d}' -e '/^* /!p' -e '${g;p}'

или наоборот

sed -n -e '/^* /{p;$!d}' -e '/^* /!H' -e '${g;p}' file    
2
27.01.2020, 20:31

Здесь один путь с awk:

awk '!/^\*/{a[++i]=$0;next}1 END{while(x<length(a))print a[++x]}' file
0
27.01.2020, 20:31
  • 1
    Один незначительный незначительный сбой: gawk 4.1.0 Я использую, требует точки с запятой между 1 и END. Это кодирует работу для Вас, как, или недостающая точка с запятой является просто проблемой вставки копии? –  manatwork 29.06.2013, 20:33
  • 2
    @manatwork Хорошо работала с awk (bsd версия) на моем Mac. Но Вы правы, я попробовал gawk v4.1.0 и это не работало. –  jaypal singh 29.06.2013, 20:35

Так как Вы добавили * символы вручную, можно только продолжить работать в интерактивном режиме. В vi, можно сделать это:

:g/pattern/m<address>

перемещать все строки, которые соответствуют шаблону к данному адресу. Если адрес будет дан как 0, то он переместит строки перед первой строкой файла. Так:

:g/^\*/m0

Обратите внимание, однако, что отмеченные строки появляются в обратном порядке! Я делал такого рода вещь много раз в прошлом. Поддерживать в порядке строки, что я делаю, перемещают их после последней строки вместо перед firstline, при помощи адреса '$' вместо '0':

:g/^\*/m$

Если я затем хочу их в передней стороне, то это - легкое ручное перемещение. Например, с помощью визуального выбора Vim.

Следующий раз, между прочим, выбирает маркер, который не является regex выходом требования оператора, хотя в этом случае Vim, оказывается, принимает :g/^*/. :)

Возможно переместить строки в конец и удалить символ маркировки за один шаг. Это работает в Vim; только проблема, я не могу вполне выследить часть документации, в которой говорится, что она, как предполагается:

:g/^*/s/^.//|m$
1
27.01.2020, 20:31

Поскольку последовательности php могут изменяться, можно использовать переменную $ url для серверных urls. Добавьте последовательности xyzserver.com/examplescript.php с соответствующим идентификатором, соответствующим потребностям разработки/подготовки/производства.

например, если это разработка

$ dev = «development»

$ dev. = «xyzserver.com/examplescript.php»

-121--244638-

Несколько вещей:

  1. Как отмечает derobert , язык и платформа Unix чувствительны к регистру.
  2. Ключевое слово then используется только с сопутствующим , если . Чтобы просто выполнить команду за другой, выберите

    • Сохранить их в различных строках:

       diff workfile1.txt workfile2.txt
      wc workfile1.txt workfile2.txt
      
    • Или разделять точкой с запятой:

       diff workfile1.txt workfile2.txt; wc workfile1.txt workfile2.txt
      
  3. Цитаты имеют значение. На некоторых вещах вы использовали довольно цитаты « вместо обычных (» ). Не используйте текстовый процессор, например MS Word или LibreOffice Writer, для редактирования сценариев. Используйте простые редакторы (например, Notepad++, gedit и т.д.) или IDE.
  4. wc перечислит число слов, строк и символов, если не указано, какие из них выводить. Используйте -w , чтобы ограничить число слов: wc -w workfile1.txt workfile2.txt
  5. Я считаю, что «сравнение двух файлов» и «поиск различий между двумя файлами» - это две неподключенные вещи. Нет, это не так. Для выполнения обоих действий можно использовать одну и ту же команду. Используйте cmp или diff . Нет необходимости использовать и то, и другое.
  6. Объединение в различных разделах двух файлов лучше всего выполнять с помощью патча , и для получения информации о патче можно использовать diff . Поэтому пропустите cmp для этого. Соответствующее чтение:

Я думаю, что вам следует начать с руководства начинающего по написанию сценариев .

-121--252940-

Вот решение, использующее ed (и немного расширяющее решение vi , размещенное Kaz, которое под ним использует ex - beefed up ed ).
Замените w на , p\n для печати выходных данных вместо записи в файл.

Переместите соответствующие строки в конец файла:

ed -s file <<< $'g/^\*/m$\nwq\n'

Подкоманда g lobal помечает каждую строку, соответствующий образец. Затем для каждой отмеченной строки устанавливает текущую строку в отмеченную строку и запускает подкоманду : m ove после строки по адресу $ (после последней строки); затем w выполнить зачет в файл и q использовать редактор.

Переместите соответствующие строки в начало файла (или, скорее, переместите несоответствующие строки в конец файла - но это конечный результат, который имеет значение -сохранить порядок строк):

ed -s file <<< $'v/^\*/m$\nwq\n'

Глобальная подкоманда in v erse помечает каждую строку, которая НЕ соответствует образцу. Затем для каждой отмеченной строки устанавливает текущую строку в отмеченную строку и запускает подкоманду : m ove после строки по адресу $ (после последней строки); затем w выполнить зачет в файл и q использовать редактор.

Причина, по которой я использую обратное совпадение для достижения желаемого результата вместо g/^\*/m0 (переместить все совпадающие строки в начало), предложенного Казом, заключается в том, что (как он указал) при перемещении совпадающих строк в начало они окажутся в обратном порядке.
Это - как я подчеркнул выше - потому что g и v , для каждой отмеченной строки, установить текущую строку для отмеченной строки и запустить указанные подкоманды . Первая строка, помеченная как совпадающая, перемещается после строки, адресуемой параметром, после m : 0 в этом случае - поэтому она становится первой строкой. Затем вторая совпадающая строка перемещается на тот же адрес, так что она становится первой строкой и строкой, которая была перемещена, прежде чем она станет второй строкой... и так далее... до тех пор, пока последняя соответствующая строка не будет перемещена на указанный адрес.

4
27.01.2020, 20:31

В зависимости от размера файла можно сделать:

sed '/^*/!H;//p;$!d;g;s/\n//'

, который складывается в H старые пробелы строк, которые не совпадают с /^*/. Те из них, которые совпадают, отображаются pв том виде, в котором они встречаются во входных данных. Затем все строки, которые соответствуют ! , а не $ последние, являются deleted из выходного сигнала. В последней строке мы gи т.д. удерживаем пробел, перезаписывая пространство шаблонов, тогда первая \newline символ s/\n///отброшен, потому что первая Hстарая строка каждый раз будет содержать по одному лишнему символу.

Для этого нужен большой буфер, так как все эти строки хранятся в старом пространстве H. Это, с другой стороны...

sed '/^*/p;$!d;g;r file' <file    |
sed -e '1,/^$/{/./p;d' -e '};/^*/d'

... не имеет этого требования.

Первая sed p печатает только /^*/ соответствующие строки до последней строки $, после чего выводит пустую строку, а затем r снова и снова выводит весь входной файл.

Вторая sed работает сначала в диапазоне строк от первой строки до первой пустой строки p, печатая все строки, которые совпадают хотя бы с одним символом, затем dподнимая лот. После того, как она встретит первую пустую строку, она затем d поднимает все строки, которые совпадают с /^*/.

9
27.01.2020, 20:31

Теги

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