Есть много способов:
Поместите гостевую машину C в ту же подсеть, что и на гостевых компьютерах A и B.
Используйте мостовое соединение вместо NAT для гостевой машины C. Тогда у вас будет доступ к гостевой машине C от гостей A и B, но гостевой компьютер C не будет имеют доступ к гостям A и B.
Разрешите пересылку на хост-сервере между интерфейсами virbr0 и virbr1. Выполните следующие команды:
iptables -I FORWARD -i virbr0 -o virbr1 -s 192.168.122.0/24 -d 192.168. 100.0 / 24 -j ACCEPT
iptables -I FORWARD -i virbr1 -o virbr0 -s 192.168.100.0/24 -d 192.168.122.0/24 -j ACCEPT
/etc/init.d/iptables save
Просто добавьте вторую виртуальную сетевую карту к машине C и подключите ее к virbr0.
Добавьте в файл с именем csv2tab.sh
и сделайте его исполняемым
#!/usr/bin/env python
import csv, sys
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))
$ echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' | ./csv2tab.sh
A C D,E,F G I K,L,M Z
$ ./csv2tab.sh < data.csv > data.tsv && head data.tsv
1A C D,E,F G I K,L,M Z
2A C D,E,F G I K,L,M Z
3A C D,E,F G I K,L,M Z
perl -lne '
my $re = qr/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/;
print join "\t", map { s/(?<!\\)"//gr =~ s/\\"/"/gr } split $re;
'
awk -v Q=\" -v FPAT="([^,]*)|(\"[^\"]+\")" -v OFS="\t" '{
for (i=1; i<=NF; ++i)
if ( substr($i, 1, 1) == Q )
$i = substr($i, 2, length($i) - 2)
print $1, $2, $3, $4, $5, $6, $7, $8
}'
Результат:
A C D,E,F G I K,L,M Z
Одним из вариантов может быть модуль perl Text::CSV, например,
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
' somefile
для демонстрации
echo 'A,,C,"D,E,F","G",I,"K,L,M",Z' |
perl -MText::CSV -lne 'BEGIN { $csv = Text::CSV->new() }
print join "\t", $csv->fields() if $csv->parse($_)
'
A C D,E,F G I K,L,M Z
Для развлечения, sed
sed -E 's/("([^"]*)")?,/\2\t/g' file
Если ваш sed
не поддерживает -E
, попробуйте использовать -r
. Если ваш sed
не поддерживает \t
для литеральной табуляции, попробуйте поставить литеральную табуляцию (во многих оболочках, ctrl-v tab) или в Bash используйте $'. ...'
в стиле C (в этом случае обратный слеш в \2
нужно удвоить). Если вы хотите сохранить кавычки, используйте \1
вместо \2
(в этом случае внутренняя пара круглых скобок бесполезна и может быть удалена).
Здесь не делается попытка обработать двойные кавычки внутри двойных кавычек; некоторые диалекты CSV поддерживают это, удваивая цитируемую двойную кавычку (sic).
Использование csvkit
утилиты (Python), например:
$ csvformat -T in.csv > out.txt
Выполняет потоковую передачу с правильным цитированием и экранированием CSV и TSV
Это в apt и других менеджерах пакетов
Решение для термоядерной мухобойки должно использовать libreoffice. Хотя https://ask.libreoffice.org/en/question/19042/is-is-possible-to-convert-comma-separated-value-csv-to-tab-separated-value-tsv-via-headless-mode/ предполагает, что это невозможно, но он ошибается (или просто устарел?) и следующая команда работает на моей 5.3. :
loffice "-env:UserInstallation=file:///tmp/LibO_Conversion" --convert-to csv: "Text - txt - csv (StarCalc)":9,34,UTF8 --headless --outdir some/path --infilter='csv:44,34,UTF8' *. csv
аргумент env
можно пропустить, но так документы не появятся в вашем недавнем документе.
Ради интереса подстановки регулярных выражений можно выполнять в Vim. Вот потенциальное четырехстрочное решение, адаптированное из: https://stackoverflow.com/questions/33332871/remove-all-commas-between-quotes-with-a-vim-regex
Кавычки удалены.
:%s/".\{-}"/\=substitute(submatch(0), ',', '_' , 'g')/g
:%s/,/\t/g
:%s/_/,/г
:%s/"//г
Чтобы написать решение, четыре строки выше (без двоеточия в начале) можно сохранить в файл, например. to_tsv.vim
. Откройте каждый CSV для редактирования с помощью Vim и source
сценария to_tsv.vim
в командной строке Vim (адаптировано из https ://stackoverflow.com/questions/3374179/run-vim-script-from-vim-commandline/8806874#8806874):
:source /path/to/vim/filename/to_tsv.vim
Я создал конвертер CSV в TSV с открытым -исходным кодом, который обрабатывает описанные преобразования. Это довольно быстро, возможно, стоит взглянуть, если -понадобится конвертировать большие файлы CSV. Инструмент является частью набора утилит eBay TSV(документации csv2tsv здесь). Для описанного входа достаточно параметров по умолчанию:
$ csv2tsv file.csv > file.tsv
При преобразовании CSV в TSV следует учитывать обработку разделителей полей и записей (, запятой и новой строки )в данных. CSV использует escape-синтаксис. Если цель состоит в том, чтобы использовать выходные данные с инструментами Unix, такими как cut
, awk
и т. д., выходные данные должны быть свободны от escape-символов. Большинство перечисленных здесь решений создают escape-последовательности в стиле CSV, когда в данных присутствуют разделители. csv2tsv
отличается от других решений тем, что производит TSV без побегов. Подробности смотрите в документации.
Чтобы увидеть, что делает конкретное решение, преобразуйте CSV-файл, содержащий запятые, символы табуляции, кавычки и символы новой строки в данных. Например:
$ echo $'Line,Field1,Field2\n1,"Comma: |,|","Quote: |""|"\n"2","TAB: |\t|","Newline: |\n|"' | <conversion-script-or-command>
Решения, генерирующие escape-последовательности, заключают в двойные кавычки поля, содержащие кавычки, символы новой строки или символы табуляции.
Нижеследующее является просто исправлением к ответу от @tripleeeтак что он удаляет любые кавычки из последнего поля так же, как и для всех других полей.
Чтобы показать, что исправлено, ниже приведен ответ tripee , а также небольшая модификация данных примера OP с добавлением кавычек вокруг последнего поля « Z ».
echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' | sed -r -e 's/("([^"]*)")?,/\2\t/g'
A C D,E,F G I K,L,M "Z"
Вы можете видеть, что ' Z ' заключено в кавычки. Это отличается от того, как обрабатываются внутренние поля. Например, «G » не имеет кавычек.
Следующая команда использует вторую замену для очистки последнего столбца:
echo 'A,,C,"D,E,F","G",I,"K,L,M","Z"' | sed -r -e 's/("([^"]*)")?,/\2\t/g' \
-e 's/\t"([^"]*)"$/\t\1/'
A C D,E,F G I K,L,M Z
С perl
, при условии, что поля csv не имеют встроенных "
или новых строк или вкладок:
perl -pe 's{"(.*?)"|,}{$1//"\t"}ge'
sed
решение (с требованиями ):Следует также обрабатывать буквальные двойные -кавычки, которые представлены парой двойных -кавычек в поле CSV.
Сначала измените все такие литералы двойных -кавычек на стенд -во флаге; затем удалите все разделители полей (одиночные двойные -кавычки )и преобразуйте разделители полей (запятые )в табуляции; затем измените позицию -во флагах на двойные -кавычки.
Здесь я использую\v
(вертикальную вкладку )в качестве подставки -во флаге для встроенных двойных -кавычек:
sed -r 's/""/\v/g; s/("([^"]+)")?,/\2\t/g; s/\v/"/g\'
Это решение основано на ваших данных CSV , не содержащих вертикальных -символов табуляции , а также на пустых полях CSV , не в кавычках.
Послеgem install csv
:
$ time </tmp/a ruby -rcsv -e'puts CSV.parse($<).map{|x|x*"\t"}'>/dev/null
0.307
$ time ruby -rcsv -e'CSV.foreach("/tmp/a"){|x|puts x*"\t"}'>/dev/null
0.367
$ time </tmp/a ruby -rcsv -ne'puts CSV.parse($_)*"\t"'>/dev/null
2.456
Разбор контекстно-зависимых форматов действительно постоянно раздражает, особенно. когда цитирование csv непоследовательно и даже нерегулярно. Вот простой awk, который каждый должен иметь возможность использовать/пересматривать. Он не такой умный, как краткий awk, но, возможно, хороший строительный блок, который легко настроить. Да, я знаю, что его можно было бы сократить, но мне нравится, чтобы многоразовый awk имел некоторую слабину.
{
mark[++nmark] = 0
thislength = length($0)
for (i=1; i<=thislength; i++) {
thisc = substr($0,i,1)
if (thisc == "\\") { i++; continue } # skip \x for any x
if (thisc == "\"") qflag = 1-qflag
if (thisc == "," && !qflag) mark[++nmark] = i
}
mark[++nmark] = thislength+1
for (i=1; i<nmark; i++) {
thiso = outfield[++noutfield] = substr($0, mark[i]+1, mark[i+1]-mark[i]-1)
if (thiso ~ /^".*"$/) {
sub(/"$/,"",outfield[noutfield])
sub(/^"/,"",outfield[noutfield])
}
}
for (i=1; i<noutfield; i++) printf "%s", outfield[i]"\t"
print outfield[noutfield]
}