мой текстовый файл похож на это:
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341
теперь я хочу удалить Liquid penetration 95% mass (m)
от моих строк для получения значений только. Как я должен сделать это?
Если существует только один =
знак, Вы могли удалить все прежде и включая =
как это:
$ sed -r 's/.* = (.*)/\1/' file
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Если Вы хотите изменить исходный файл, используйте -i
опция после тестирования:
sed -ri 's/.* = (.*)/\1/' file
-r
используйте ДО, таким образом, мы не должны выходить (
и )
s/old/new
замена old
с new
.*
любое количество любых символов(things)
сохранить things
к обратной ссылке позже с \1
, \2
, и т.д. Это - задание для awk
; принятие значений происходит в последнем поле только (согласно Вашему примеру):
awk '{print $NF}' file.txt
NF
awk
переменная, расширяется до количества полей в записи (строка), следовательно $NF
(отметьте $
впереди), содержит значение последнего поля. Пример:
% cat temp.txt
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341
% awk '{print $NF}' temp.txt
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
С grep
и -P
для того, чтобы иметь PCRE
(Интерпретируют шаблон как Эрл P - Compatible Regular Expression), и -o
для печати одного только подобранного шаблона. Эти \K
уведомляют, проигнорирует подобранную часть, прибывшую перед собой.
$ grep -oP '.*= \K.*' infile
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Или Вы могли использовать cut
команда вместо этого.
cut -d= -f2 infile
Так как префикс строки всегда имеет ту же длину (34 символа), можно использовать cut
:
cut -c 35- < input.txt > output.txt
Инвертируйте содержание файла с rev
, передайте вывод по каналу в cut
с пространством как разделитель и 1 как целевое поле, затем инвертируйте его снова для получения исходного числа:
$ rev your_file | cut -d' ' -f1 | rev
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Я решил сравнить различные решения, перечисленные здесь. С этой целью я создал большой файл, на основе содержания, обеспеченного OP:
Я создал простой файл, названный input.file
:
$ cat input.file
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341
Затем я выполнил этот цикл:
for i in {1..100}; do cat input.file | tee -a input.file; done
Окно терминала было заблокировано. Я выполнился killall tee
от другого терминала. Затем я исследовал содержание файла командами: less input.file
и cat input.file
. Это выглядело хорошим, кроме последней строки. Таким образом, я удалил последнюю строку и создал резервную копию: cp input.file{,.copy}
(из-за команд, которые используют оперативную опцию).
Заключительное количество строк в файл input.file
2 192 473. Я получил то число командой wc
:
$ cat input.file | wc -l
2192473
Вот результат сравнения:
$ time grep -o '[^[:space:]]\+$' input.file > output.file real 0m58.539s user 0m58.416s sys 0m0.108s
$ time sed -ri 's/.* = (.*)/\1/' input.file real 0m26.936s user 0m22.836s sys 0m4.092s
Кроме того, если мы перенаправляем вывод в новый файл, команда больше быстрее:
$ time sed -r 's/.* = (.*)/\1/' input.file > output.file real 0m19.734s user 0m19.672s sys 0m0.056s
gawk '{gsub(".*= ", "");print}'
$ time gawk '{gsub(".*= ", "");print}' input.file > output.file real 0m5.644s user 0m5.568s sys 0m0.072s
$ time rev input.file | cut -d' ' -f1 | rev > output.file real 0m3.703s user 0m2.108s sys 0m4.916s
$ time grep -oP '.*= \K.*' input.file > output.file real 0m3.328s user 0m3.252s sys 0m0.072s
sed 's/.*= //'
(соответственно -i
опция делает команду несколько раз медленнее),
$ time sed 's/.*= //' input.file > output.file real 0m3.310s user 0m3.212s sys 0m0.092s
perl -pe 's/.*= //'
( -i
опция не производит большую разницу в производительности здесь),
$ time perl -i.bak -pe 's/.*= //' input.file real 0m3.187s user 0m3.128s sys 0m0.056s
$ time perl -pe 's/.*= //' input.file > output.file real 0m3.138s user 0m3.036s sys 0m0.100s
$ time awk '{print $NF}' input.file > output.file real 0m1.251s user 0m1.164s sys 0m0.084s
$ time cut -c 35- input.file > output.file real 0m0.352s user 0m0.284s sys 0m0.064s
$ time cut -d= -f2 input.file > output.file real 0m0.328s user 0m0.260s sys 0m0.064s
perl
- замените шаблоном /.*= /
с пустой строкой //
:
perl -pe 's/.*= //' input.file > output.file
perl -i.bak -pe 's/.*= //' input.file
От perl --help
:
-e program one line of program (several -e's allowed, omit programfile)
-p assume loop like -n but print line also, like sed
-i[extension] edit <> files in place (makes backup if extension supplied)
sed
- замените шаблоном с пустой строкой:
sed 's/.*= //' input.file > output.file
или (но медленнее, чем вышеупомянутое):
sed -i.bak 's/.*= //' input.file
gawk
- замените шаблоном ".*= "
с пустой строкой ""
:
gawk '{gsub(".*= ", "");print}' input.file > output.file
От man gawk
:
gsub(r, s [, t]) For each substring matching the regular expression r in the string t,
substitute the string s, and return the number of substitutions.
If t is not supplied, use $0...
Это просто, коротко, и легко записать, понять, и проверить, и мне лично нравится он:
grep -oE '\S+$' file
grep
в Ubuntu при вызове с -E
или -P
, берет стенографию \s
означать пробельный символ (на практике обычно пространство или вкладка) и \S
означать что-либо, что не является тем. Используя квантор +
и привязка конца строки $
, шаблон \S+$
соответствия один или несколько непробелов в конце строки. Можно использовать -P
вместо -E
; значение в этом случае является тем же, но другой механизм регулярных выражений используется, таким образом, у них могут быть различные рабочие характеристики.
Это эквивалентно прокомментированному решению Avinash Raj (только с более легким, более компактным синтаксисом):
grep -o '[^[:space:]]\+$' file
Эти подходы не будут работать, если там мог бы запаздывать пробел после числа. Они могут быть изменены так, они делают, но я не вижу никакой смысл во входе в это здесь. Хотя это иногда поучительно для обобщения решения работать под большим количеством случаев, это не практично для делания так почти так часто, как люди склонны принимать, потому что у каждого обычно нет способа знать, в каком из многих различных несовместимых путей проблема, возможно, в конечном счете должна была бы быть обобщена.
Производительность иногда является важным фактором. Этот вопрос не предусматривает, что вход является очень большим, и вероятно, что каждый метод, который был отправлен здесь, достаточно быстр. Однако в случае, если скорость желаема, вот маленький сравнительный тест на десяти миллионах входных файлов строки:
$ perl -e 'print((<>) x 2000000)' file > bigfile
$ du -sh bigfile
439M bigfile
$ wc -l bigfile
10000000 bigfile
$ TIMEFORMAT=%R
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
819.565
$ time grep -oE '\S+$' bigfile > bigfile.out
816.910
$ time grep -oP '\S+$' bigfile > bigfile.out
67.465
$ time cut -d= -f2 bigfile > bigfile.out
3.902
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
815.183
$ time grep -oE '\S+$' bigfile > bigfile.out
824.546
$ time grep -oP '\S+$' bigfile > bigfile.out
68.692
$ time cut -d= -f2 bigfile > bigfile.out
4.135
Я выполнил его дважды в случае, если порядок имел значение (как это иногда делает для задач I/O-heavy), и потому что у меня не было машины доступной, который не делал другого материала в фоновом режиме, который мог скосить результаты. От тех результатов я завершаю следующее, по крайней мере временно и для входных файлов размера я использовал:
Ничего себе! Передача -P
(для использования PCRE), а не -G
(значение по умолчанию, когда никакой диалект не указан), или -E
сделанный grep
быстрее по порядку величины. Таким образом для больших файлов, может быть лучше использовать эту команду, чем один показанный выше:
grep -oP '\S+$' file
WOW!! cut
метод в ответе αғsнιη, cut -d= -f2 file
, по порядку величины, более быстрому, чем даже более быстрая версия моего пути! Это был победитель в сравнительном тесте pa4080 также, который покрыл больше методов, чем это, но с меньшим входом - и который является, почему я выбрал его, всех других методов, для включения в мой тест. Если производительность важна, или файлы огромны, я думаю αғsнιη cut
метод должен использоваться.
Это также служит напоминанием что простое cut
и paste
об утилитах нельзя забыть и нужно, возможно, предпочесть, когда применимо, даже при том, что существуют более сложные инструменты как grep
это часто предлагается как решения первой строки (и что я являюсь лично более приученным к использованию).