Входной файл: Test.txt.
-rw-r--r-- 1 dev dev 93K Sep 18 05:37 Server-23091805496-2-AC.log
-rw-r--r-- 1 dev dev 40K Sep 18 05:44 ServerM-23090331-5709-log.log
-rw-r--r-- 1 dev dev 484K Sep 18 05:46 Server-280334-12570-log.log
-rw-r--r-- 1 dev dev 235K Sep 18 05:47 Server-233405500-1-AC.log
Вывод в 1-м файле:
Sep 18 05:37 Server-23091805496-2-AC.log
Sep 18 05:44 ServerM-23090331-5709-log.log
Sep 18 05:46 Server-280334-12570-log.log
Sep 18 05:47 Server-233405500-1-AC.log
Вывод во втором файле:
Server-23091805496-2-AC.log
ServerM-23090331-5709-log.log
Server-280334-12570-log.log
Server-233405500-1-AC.log
Пробовал ниже: 1. sed 's/ /\n/g' Test.txt 2. ls -ltr | grep "18 сентября 08:" |sed -n '1p'|cut -d ' ' -f2
Пожалуйста, прочитайте mywiki.wooledge.org/ParsingLs





Эта работа для awk, а не для sed. Попробуй это:
$ echo '-rw-r--r-- 1 dev dev 93K Sep 18 05:37 Server-23091805496-2-AC.log' | awk '{print $1}'
-rw-r--r--
$ echo '-rw-r--r-- 1 dev dev 93K Sep 18 05:37 Server-23091805496-2-AC.log' | awk '{print $5}'
93K
$ echo '-rw-r--r-- 1 dev dev 93K Sep 18 05:37 Server-23091805496-2-AC.log' | awk '{print $9}'
Server-23091805496-2-AC.log
Но требование выполнено :)
Если имя файла i. е. foo bar .baz, вы бы напечатали только foo. Вам необходимо распечатать все, начиная с поля 9 и до конца.
Вы сказали: «Эта работа предназначена для awk, а не для sed». ... Смотрите мой ответ !
Отличный ответ, но удобнее это делать с помощью awk.
Одним из ответов может быть:
sed <input.txt -e 's/.*K //g;w file1.txt' -e 's/.* //g;' >file2.txt
Или лучше:
sed <input.txt -e '
s/^\([^[:space:]]\+[[:space:]]\+\)\{5\}//;
w file1.txt' -e '
s/\([^[:space:]]\+[[:space:]]\+\)\{3\}//;' >file2.txt
Где
sed запускается только один раз, без перехода на другой инструмент,
1-й удалить все до K в первом предложении,
удаление непробелов, за которыми следуют пробелы, повторяется 5 раз, во втором предложении
тогда w напиши в файл file1.txt
На этом этапе первая часть сценария заканчивается второй кавычкой, затем вторая часть сценария начинается с аргумента -e sed (объяснения по этому поводу см. в комментарии stevesliva).
Удаление всего до последнего пробела в первом предложении,
удаление непробелов, за которыми следуют пробелы, повторяется 3 раза, во втором предложении
Затем отправьте стандартный вывод sed на file2.txt.
Если ls -l отображает дату на каком-либо языке, например день французской печати, в качестве 1-го поля, выровненного по 2 символам (%2d), чтобы сохранить выравнивание поля дня в file1.txt, вы можете добавить небольшое требование в 2 символа в 1-й sed команде:
ls -l /some/path | sed -e '
s/^\([^[:space:]]\+[[:space:]]\+\)\{5\}\( [0-9] \|[0-9]\{2\} \|[A-Z]\)/\2/;
w file1.txt' -e '
s/^ \?\([^[:space:]]\+[[:space:]]\+\)\{3\}//;' >file2.txt
Таким образом, первое поле — это либо пробел, за которым следует цифра, либо две цифры. (Добавьте потенциальный пробел в начале последней команды замены).
Примечание. Здесь я использовал перенаправление ввода (<input.txt), но в этом нет необходимости. Пожалуйста, прочитайте мой комментарий в ответ на комментарий Марка Сетчелла.
Спасибо!! Можете ли вы дать объяснение каждому полю между s и g?
@Shr Ответ отредактирован!
Почему вы используете перенаправление ввода, пожалуйста? Я имею в виду sed <input.txt ..., а не sed -e ... -e ... input.txt
@MarkSetchell Из-за моего способа размышления... я провел несколько тестов, используя ls -l | ..., поэтому подумал о фильтре. Использование перенаправления — естественный способ работы с фильтром. В любом случае вы правы, перенаправление использовать не нужно.
Спасибо, что нашли время объяснить.
@MarkSetchell Спасибо за ваш комментарий. Я процитировал их в своем ответе!
Я бы назвал отдельные аргументы -e командами, а не скриптами. GNU sed позволяет использовать несколько -e для обозначения разрыва строки (необходимого для команды w), но, как и любой sed, алгоритм запускает один сценарий из одной или нескольких команд для каждой загрузки буфера шаблонов из входного потока. Вы можете иметь метки для команд ветки в нескольких -e... они определяют один скрипт.
@stevesliva спасибо за комментарий. Я отредактировал свой ответ, добавив на них ссылку!
Это может сработать для вас (GNU sed):
sed -Ene 'h;s/\s*\S*//6g;G;s/(.*)\n\1\s*//;w file1'
-e 'h;s/\s*\S*//4g;G;s/(.*)\n\1\s*//;w file2' file
Создайте маску строк, которые хотите удалить, удалите их и запишите результат в файл.
В этом случае выполните операцию дважды для второго файла.
Использование rev и awk
$ rev Test.txt|awk 'NF=4'|rev
Sep 18 05:37 Server-23091805496-2-AC.log
Sep 18 05:44 ServerM-23090331-5709-log.log
Sep 18 05:46 Server-280334-12570-log.log
Sep 18 05:47 Server-233405500-1-AC.log
$ rev Test.txt|awk 'NF=1'|rev
Server-23091805496-2-AC.log
ServerM-23090331-5709-log.log
Server-280334-12570-log.log
Server-233405500-1-AC.log
Поскольку записи в правом столбце являются именами файлов, замена пробела приведет к уничтожению имен файлов, в которых есть пробел. Однако ваша команда
cutдолжна выбирать не поле 2, а все поля, начинающиеся с поля 9 (имя файла), т. е.cut -d ' ' -f 9-.