2010-05-26 2 views
9

У меня есть текстовый файл ("input.txt") в формате:UNIX: Заменить Newline ж/Colon, сохраняющих Newline Перед EOF

A<LF> 
B<LF> 
C<LF> 
D<LF> 
X<LF> 
Y<LF> 
Z<LF> 
<EOF> 

, который мне нужно переформатировать, чтобы:

A:B:C:D:X:Y:Z<LF> 
<EOF> 

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

Я думаю, что правильным инструментом для этой работы будет «tr». Я могу заменить все новые строки двоеточиями с помощью команды:

cat INPUT.txt | tr '\n' ':' 

Есть 99% моей работы. У меня теперь есть проблема. Заменив все новые строки двоеточиями, я не только получаю посторонний двоеточие в конце последовательности, но также теряю возврат каретки в конце ввода. Это выглядит так:

A:B:C:D:X:Y:Z:<EOF> 

Теперь мне нужно удалить двоеточие с конца ввода. Однако, если я попытаюсь передать этот обработанный ввод через «sed», чтобы удалить окончательный двоеточие (которое теперь, я думаю, будет правильным использованием «sed»), я столкнулся со второй проблемой. Вход больше не завершается новой строкой! «sed» не подходит для всех команд, потому что никогда не находит конца первой строки ввода!

Кажется, что добавление новой строки в конец некоторого ввода - очень, очень общая задача, и учитывая, что я сам был очень соблазнен написать программу, чтобы сделать это в C (что потребовало бы около восьми строк кода), Я не могу себе представить, что еще нет очень простого способа сделать это с помощью инструментов, уже доступных вам в ядре Linux.

ответ

13

Это должно сделать работу (cat и echo не нужны):

tr '\n' ':' < INPUT.TXT | sed 's/:$/\n/' 

Использование только sed:

sed -n ':a; $ ! {N;ba}; s/\n/:/g;p' INPUT.TXT 

Bash без внешнеположенности:

string=($(<INPUT.TXT)) 
string=${string[@]/%/:} 
string=${string//: /:} 
string=${string%*:} 

Использование цикла в sh:

colon='' 
while read -r line 
do 
    string=$string$colon$line 
    colon=':' 
done < INPUT.TXT 

Использование AWK:

awk '{a=a colon $0; colon=":"} END {print a}' INPUT.TXT 

Или:

awk '{printf colon $0; colon=":"} END {printf "\n" }' INPUT.TXT 

Edit:

Вот еще один способ в чистом Баш:

string=($(<INPUT.TXT)) 
saveIFS=$IFS 
IFS=':' 
newstring="${string[*]}" 
IFS=$saveIFS 

Edit 2:

Вот еще один способ, который делает использования echo:

echo "$(tr '\n' ':' < INPUT.TXT | head -c -1)" 
+0

Я был сначала озадачен тем, почему вы отправляете сообщение в качестве решения. То, что я сказал, не работает, поэтому я попробовал его на другой машине. Я понял, что сервер Sun, в котором я нуждался, не использовал GNU 'sed'. Версия «sed» на сервере терпит неудачу, когда вход не имеет завершающей новой строки, поэтому, как указано, почему я использовал «эхо». ((Сервер - это критически важное устройство на работе, которое никогда не срабатывало, и, таким образом, оно никогда не перезапускалось, не говоря уже об обновлении, в течение многих лет. Добро пожаловать в мою жизнь.)) Решение оболочки оболочки является удивительным, хотя , – Maarx

+0

/bin/sed на солнце ... ick. Как насчет/usr/xpg4/bin/sed? –

1

Вот еще одно решение: (предполагается, что набор символов, где ':' является восьмеричных 72, например, ascii)

 
perl -l72 -pe '$\="\n" if eof' INPUT.TXT 

 Смежные вопросы

  • Нет связанных вопросов^_^