*
в шаблонах оболочки соответствует 0 или более символам. Его не следует путать с оператором регулярного выражения *
, который означает 0 или более из предыдущего атома .
В базовых шаблонах оболочки нет эквивалента регулярного выражения *
. Однако в различных оболочках для этого есть расширения.
ksh
имеет * (что-то)
:
ls a _ * ([az]) _ data
вы можете иметь то же самое в bash
с shopt -s extglob
или zsh
с setopt kshglob
:
shopt -s extglob
ls a _ * ([az] ) _data
В zsh
с включенным extendedglob
, #
эквивалентно регулярному выражению *
:
setopt extendedglob
ls a_ [az] #_ data
В последних версиях ksh93
вы также можете использовать регулярные выражения в глобах. Здесь с расширенными регулярными выражениями:
ls ~ (E: a_ [az] * _ data)
Обратите внимание, что [az]
соответствует разным вещам в зависимости от на текущей локали. Обычно он сопоставляет только 26 a
- z
латинские буквы без акцента в локали C
. В других регионах это обычно соответствует большему количеству и не всегда имеет смысл. Чтобы соответствовать букве в вашем языковом стандарте, вы можете предпочесть [[: alpha:]]
.
Я мог бы подойти к этому с помощью awk таким образом:
-F,
"\""
. Скрипт:
awk -F, 'BEGIN{ OFS=FS } {$1="\""$1"\""; $5="\""$5"\""; $6="\""$6"\""; print }' < input.csv > output.csv
Когда вы обнаружите, что вам нужно указать больше полей, просто сделайте то же самое, что и с полями 1, 5 и 6 выше.
Если вы действительно хотите использовать sed
(, что я не рекомендую, если доступны awk
или perl
), тогда предположим, что шестой столбец заканчивается строкой, а не запятой И что поля сами по себе не содержат встроенных (кавычек )запятых:
sed -E -e 's/([^,]*),/"\1",/1' -e 's/([^,]*),/"\1",/5' -e 's/([^,]*)$/"\1"/' file
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
Общий шаблон — s/([^,]*),/"\1",/n
, где n
относится к n-му вхождению нуля или более символов, отличных от -,
, за которыми следует ,
, а \1
— это ссылка на захваченный шаблон (в круглых скобках. ).
Сperl
$ perl -F, -lane 'map {$_=qq("$_")} @F[0,4,5]; print join ",", @F' ip.txt
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
-F,
использовать ,
в качестве разделителя полей ввода, результаты доступны в массиве @F
map {$_=qq("$_")} @F[0,4,5]
обязательные элементы массива в двойных кавычках. Индекс начинается с 0
. Оператор qq
используется здесь, чтобы избежать экранирования двойных кавычек, qq("$_")
такой же, как"\"$_\""
print join ",", @F
напечатать измененный массив с ,
в качестве разделителя
Другой способ сделать сawk
$ awk -v q='"' 'BEGIN{split("1 5 6",a); FS=OFS=","}
{for(i in a) $a[i]=q $a[i] q} 1' ip.txt
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
-v q='"'
сохранить двойную кавычку как значение в переменной q
split("1 5 6",a)
индекс сохранения будет изменен как значения в a
массиве (по умолчанию разделен на пробелы, FS еще не изменен)FS=OFS=","
изменить разделитель ввода/вывода на,
for(i in a) $a[i]=q $a[i] q
изменить обязательные поля 1
идиоматический способ распечатать содержимое$0
Использованиеcsvtool
с полезной командой format
:
csvtool format '"%1",%2,%3,%4,"%5","%6"\n' file.csv
Пример:
echo "2018-03-18 4:56:17,255.255.255.255,00,ssh,admin,123" |
csvtool format '"%1",%2,%3,%4,"%5","%6"\n' -
Выход:
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","123"
csvtool
также могут call
функции оболочки и внешние программы для разбора строк из файлов.CSV . Чтобы сделать то же самое, используя printf
, но выведите «123 » в шестнадцатеричном формате, выполните:
echo "2018-03-18 4:56:17,255.255.255.255,00,ssh,admin,123" |
csvtool call "printf '\"%s\",%s,%s,%s,\"%s\",\"%x\"\n'" -
Выход:
"2018-03-18 4:56:17",255.255.255.255,00,ssh,"admin","7b"
Для этого существует простой способ :использовать escape-символ \, когда вы ставите " перед и в конце столбца.
cat test.txt | awk '{ print $1" ""\""$2"\""}'
Попробуйте.