У меня очень большой CSV-файл. Как бы вы удалили самое последнее ,
с помощью sed (или аналогичного)?
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0],
]
Желаемый вывод
...
[11911,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11912,0,"BUILDER","2014-10-15","BUILDER",0,0],
[11913,0,"BUILDER","2014-10-15","BUILDER",0,0]
]
Следующая команда sed удалит последнее вхождение на строку, но я хочу на файл.
sed -e 's/,$//' foo.csv
И это не работает
sed '$s/,//' foo.csv
Ответы:
С помощью
awk
Если запятая всегда находится в конце от второй до последней строки:
Использование
awk
иbash
С помощью
sed
Для OSX и других платформ BSD попробуйте:
С помощью
bash
источник
sed: 1: "x;${s/,$//;p;x}; 2,$ p": extra characters at the end of x command
sed
и он часто отличается тонким образом. У меня нет доступа к OSX, чтобы проверить это, но, пожалуйста, попробуйтеsed -n -e x -e '${s/,$//;p;x;}' -e '2,$ p' input
Просто вы можете попробовать приведенную ниже команду Perl one-liner.
Объяснение:
,
Соответствует запятой.(?!.*,)
Отрицательный взгляд утверждает, что после этой соответствующей запятой не будет запятой. Так что это будет соответствовать последней запятой.s
И самаяs
важная вещь - это модификатор DOTALL, который делает точку подходящей даже для символов новой строки.источник
perl -0777 -pi -e 's/(.*),(.*?)/\1\2/s'
. Это работает, потому что первый.*
жадный, а второй нет.Это должно удалить только последнее вхождение a
,
в любом входном файле - и он все равно будет печатать те, в которых a,
не встречается. По сути, он буферизует последовательности строк, которые не содержат запятой.Когда он встречает запятую, он заменяет текущий буфер строк на буфер удержания и, таким образом, одновременно распечатывает все строки, которые произошли после последней запятой, и освобождает свой буфер удержания.
Я просто копался в моем файле истории и нашел это:
Это на самом деле очень хорошо. Да, он использует
eval
, но никогда не передает ему ничего, кроме числовой ссылки на его аргументы. Он создает произвольныеsed
сценарии для обработки последнего совпадения. Я покажу тебе:Это выводит следующее на stderr. Это копия
lmatch
ввода:Функция
eval
ed subshell повторяет все свои аргументы один раз. Проходя по ним, он выполняет итерацию счетчика в зависимости от контекста для каждого переключателя и пропускает столько аргументов для следующей итерации. С тех пор он делает одну из нескольких вещей на аргумент:$a
к$o
.$a
назначается на основе значения,$i
которое увеличивается на число аргументов для каждого обработанного аргумента.$a
присваивается одно из двух следующих значений:a=$((i+=1))
- это присваивается, если к короткой опции не добавлен аргумент, или если опция была длинной.a=$i#-?
- это назначается , если опция является коротким и вовсе есть ее аргумент прилагается к нему.a=\${$a}${1:+$d\${$(($1))\}}
- Независимо от начального присваивания$a
значение всегда заключено в фигурные скобки и - в-s
случае - иногда$i
увеличивается на единицу и добавляется дополнительное поле с разделителями.В результате
eval
никогда не передается строка, содержащая какие-либо неизвестные. Каждый из аргументов командной строки именуется их числовым номером аргумента - даже разделителем, который извлекается из первого символа первого аргумента и является единственным случаем, когда вы должны использовать любой символ, который не экранирован. По сути, функция является генератором макросов - она никогда не интерпретирует значения аргументов каким-либо особым образом, потому чтоsed
может (и, конечно, легко ) справиться с этим при синтаксическом анализе сценария. Вместо этого он просто разумно организует свои аргументы в работоспособный скрипт.Вот некоторые отладочные выходные данные функции на работе:
И поэтому
lmatch
его можно использовать для простого применения регулярных выражений к данным после последнего совпадения в файле. Результат команды, которую я запустил выше:... который с учетом подмножества файла, который следует за последним
/^.0/
совпадением, применяет следующие замены:sdd&&&&d
- заменяет$match
собой 4 раза.sd'dsqd4
- четвертая одинарная кавычка, следующая за началом строки после последнего матча.sd"d\dqd2
- то же самое, но для двойных кавычек и глобально.Итак, чтобы продемонстрировать, как можно использовать
lmatch
для удаления последней запятой в файле:ВЫХОД:
источник
-m
опцию и сделал ее обязательной, переключился на несколько аргументов для re и repl для,-s
а также реализовал правильную обработку разделителей. Я думаю, что это пуленепробиваемый. Я успешно использовал пробел и одинарную кавычку в качестве разделителя,Если запятая не может быть в последней строке
Использование
awk
иtac
:Это
awk
простая команда, которая выполняет подстановку при первом просмотре шаблона.tac
меняет порядок строк в файле, поэтомуawk
команда удаляет последний запятую.Мне сказали, что
может быть более эффективным.
источник
Если вы можете использовать
tac
:источник
см. /programming/12390134/remove-comma-from-last-line
Это работает для меня:
Мой лучший способ - удалить последнюю строку и после удаления запятой добавить символ] снова
источник
Попробуйте с ниже
vi
:Объяснение:
$-1
выберите вторую строку до последнейs
замещать\(,\)\(\_s*]\)
найти запятую, за которой]
следует пробел или символ новой строки\2
заменить\(\_s*]\)
то есть пробелами или символом новой строки с последующим]
источник
Попробуйте с приведенной ниже
sed
командой.источник