2012-02-15 4 views
2

Так что я получил в текстовый файл, где каждая строка представляет собой путь к файлу, я хотел бы:Удалить все строки в текстовом файле, которые не содержат строку

  1. Прочитайте этот текстовый файл (LINE- построчно).
  2. Удалить все строки, которые не заканчиваются ,-,.txt
  3. В остальных строках, удалите все из после последнего / к ,-,.txt.
  4. Напишите вывод на новый txt.

Как это можно сделать с sed?

Вход:

/a/b1/ 
/a/b1/car 
/a/b1/car/bil/ 
/a/b1/car/bil/,-,.txt 
/a/b2/ 
/a/b2/flower 
/a/b2/flower/bil/ 
/a/b2/flower/bil/,-,.txt 
/a/b2/ 
/a/b2/boat 
/a/b2/boat/baat/ 
/a/b2/boat/baat/abc,-,.txt 

Второй шаг:

/a/b1/car/bil/,-,.txt 
/a/b2/flower/bil/,-,.txt 
/a/b2/boat/baat/abc,-,.txt 

Третий шаг/желаемый результат:

/a/b1/car/bil/ 
/a/b2/flower/bil/ 
/a/b2/boat/baat/ 
+2

Пожалуйста разместить образец. –

+1

Короткий образец для тестирования был бы прекрасен. Кроме того, каждый должен производить свои собственные. –

+1

'sed' - это редактор потоков. Он не считывает весь файл в память; он (обычно) считывает и обрабатывает строку за раз. Это должно быть именно то, что вам нужно для ваших требований (игнорируя № 1). –

ответ

3
sed -n '/,-,\.txt$/s|/[^/]*$||p' input.txt > output.txt 

Что он делает:

Она читает построчно из input.txt; -n сообщает, что он не печатает строки по умолчанию. Для каждой строки, которая соответствует шаблону ,-,\.txt$, все, состоящее из знака /, за которым следуют ноль или более символов не /, до конца строки удаляется (т. Е. От последних/ до конца строки); Я использую | как разделитель, поэтому мне не нужно бежать из /.

Это довольно простое исполнение ваших требований.

Теперь, когда Вы разместили вход и выход пробы, я вижу, что вы хотите сохранить окончательный / (что не согласуется с вашим требованием «удалить все от последнего / к ,-,.txt»). Для этого:

sed -n '/,-,\.txt$/s|/[^/]*$|/|p' input.txt > output.txt 

Это дает ожидаемые результаты с учетом ввода образца.

Если бы я делал это на лету, я мог бы использовать более простой подход, сочетающий в себе sed и grep:

grep ',-,\.txt$' input.txt | sed 's|/[^/]*$|/|' > output.txt 
+0

Я тестировал его, отлично работает –

1

Должен ли он быть СЭД? я бы использовал python для такой вещи, sed быстро усложнился.

#!/usr/bin/env python 
import sys 

def main(fin, fout): 
    with open(fin) as f: 
     lines = [] 
     for line in f.readlines(): 
      if line.endswith(',-,.txt\n'): 
       lines.append('/'.join(line.split('/')[:-1]) + '/\n') 

    with open(fout, 'w') as f: 
     for line in lines: 
      f.write(line) 

def usage(): 
    print sys.argv[0], "filename new_file" 
    print 'remove all lines not ending with ",-,.txt"' 
    print 'print the resulting lines, up to their last "/" to new file' 


if __name__ == '__main__': 
    if len(sys.argv) == 3: 
     main(sys.argv[1], sys.argv[2]) 
    else: 
     usage() 

испытания с образцом

/a/b1/car/bil/ 
/a/b2/flower/bil/ 
/a/b2/boat/baat/ 
+0

нет, python будет просто отлично, (вопрос обновлен) –

+1

обновлено, оно должно работать для вашего прецедента, было просто ответы с sed, поскольку – Tshirtman

+0

Решение sed Keith - 24 символа длинный. Вы действительно думаете, что это «слишком сложно»? Решение python выглядит намного сложнее. –

1
echo -e "foo,-,.txt\nbar,-,.png" | sed -rn '/,-,\.txt/{s/^(.*),-,\.txt$/\1/p}' 

объяснение:

sed -rn : 
    -r : use regular expressions, which allows (.*) as 
      capturing group without masking the parens. 
    -n : no output by default 
    '/pattern/{ list of commands}' 
    {s/pattern/replacement/p} substitute pattern with replacement, 
     then print. 
    /^(.*)foo$/ : from line begin^to line end $, with anything 
     before foo being captured, to be outputted with \1 
0

Это должно сделать работу:

sed -r '/,-,\.txt$/!d' <file> | awk -F, '{print $1}' 

Примечания:

  • Команда sed удаляет строки, которые не соответствуют шаблону (!d)
  • В awk команда печатает только первое поле в строке с несколькими полями, разделенных запятыми. Кажется, это то, что вы ищете в зависимости от ввода и желаемого вывода, заданного в вопросе.
0

в вашем вопросе вы показали нам два шага, это приемлемо, если это делается в одном короткий от sed onliner?

sed -r '/,-,\.txt/!d; s#/[^/]*$#/#' yourFile 

работает с данными вашего примера.

см тест ниже:

kent$ cat t.txt 
/a/b1/ 
/a/b1/car 
/a/b1/car/bil/ 
/a/b1/car/bil/,-,.txt 
/a/b2/ 
/a/b2/flower 
/a/b2/flower/bil/ 
/a/b2/flower/bil/,-,.txt 
/a/b2/ 
/a/b2/boat 
/a/b2/boat/baat/ 
/a/b2/boat/baat/abc,-,.txt 

kent$ sed -r '/,-,\.txt/!d; s#/[^/]*$#/#' t.txt 
/a/b1/car/bil/ 
/a/b2/flower/bil/ 
/a/b2/boat/baat/ 
1
$ grep -oP '.*/(?=[^/]*,-,\.txt$)' input.txt 
/a/b1/car/bil/ 
/a/b2/flower/bil/ 
/a/b2/boat/baat/ 
0

Это может работать для вас:

sed 's/[^/]*,-,\.txt$//p;d' file 
Смежные вопросы