Найдите шаблон (ГГГГ-ММ-ДД) и замените его тем же значением, конкатенируя с апострофами. - PullRequest
0 голосов
/ 28 января 2019

У меня есть такие данные:

1,1990-01-01,2,A,2015-02-09 
1,NULL,2,A,2015-02-09
1,1990-01-01,2,A,NULL

И ищу решение, которое заменит каждую дату в файле старым значением, но с добавлением апострофов.В основном ожидаемый результат от примера будет:

1,'1990-01-01',2,A,'2015-02-09' 
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

Я нашел способ найти шаблон, который соответствует моей дате, но все еще не могу получить то, что я могу затем заменить.

sed 's/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/????/' a.txt > b.txt

Ответы [ 6 ]

0 голосов
/ 29 января 2019

С Perl это просто

perl -pe ' s/(\d{4}-\d\d-\d\d)/\x27$1\x27/g '

с входными данными - \ x27 используется для одинарных кавычек

$ cat liubo.txt
1,1990-01-01,2,A,2015-02-09
1,NULL,2,A,2015-02-09
1,1990-01-01,2,A,NULL

$ perl -pe ' s/(\d{4}-\d\d-\d\d)/\x27$1\x27/g ' liubo.txt
1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

$

Если вы хотите использовать одинарные кавычки, тогда экранируйте $ и переноситекоманда в двойных кавычках

$ perl -pe " s/(\d{4}-\d\d-\d\d)/\'\$1\'/g " liubo.txt
1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL

$
0 голосов
/ 29 января 2019

С GNU sed:

sed -E 's/([0-9]{2,4}-?){3}/'\''&'\''/g' file

В зависимости от содержимого вашего файла, даты также могут быть описаны как 1 или 2, за которыми следует комбинация из девяти тире или цифр:

sed -E 's/[12][-0-9]{9}/'\''&'\''/g" file
0 голосов
/ 28 января 2019

Не могли бы вы попробовать следующее. (REGEX, упомянутый внутри match, может быть записан как [0-9]{4}-[0-9]{2}-[0-9]{2}, но так как мой awk имеет старую версию, поэтому не может его протестировать, вы можете попробовать его один раз)

awk -v s1="'" '
{
   while(match($0,/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/)){
      val=val substr($0,1,RSTART-1) s1 substr($0,RSTART,RLENGTH) s1
      $0=substr($0,RSTART+RLENGTH)
   }
   print val
   val=""
}'   Input_file

Вывод будет следующим.

1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01'
0 голосов
/ 28 января 2019

Вам необходимо использовать группу захвата, а также заменить все совпадающие вхождения на флаг g.

sed 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'"'"'\1'"'"'/g' a.txt > b.txt

Текст замены немного сбивает с толку, поскольку одинстрока в кавычках в оболочке не может содержать одинарных кавычек, поэтому необходимо закрыть строку в одинарных кавычках, а затем использовать двойные кавычки.Использование кавычек в стиле $'...' в bash немного упрощает это, за счет необходимости избежать обратной косой черты.

sed $'s/\\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\\)/\'\1\'/g' a.txt > b.txt

Или вы можете просто заключить в кавычки скрипт, так как в настоящее время ничего нетв нем, который подлежит расширению:

sed "s/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'\1'/g" a.txt > b.txt

Существует также специальный & текст замены, который расширяется до того, что соответствует регулярным выражениям, поэтому вы можете избежать явной группы захвата:

sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/'&'/g" a.txt > b.txt
0 голосов
/ 28 января 2019

Вот один в awk:

$ awk -v q="'" '
BEGIN { FS=OFS="," }                         # set selimiters
{
    for(i=1;i<=NF;i++)                       # loop all fields
        if($i~/[0-9]{4}-[0-9]{2}-[0-9]{2}/)  # if field has a date looking string
            $i=q $i q                        # quote it
}1' file

Вывод:

1,'1990-01-01',2,A,'2015-02-09'
1,NULL,2,A,'2015-02-09'
1,'1990-01-01',2,A,NULL
0 голосов
/ 28 января 2019

Поймать дату в группе, заключив шаблон в круглые скобки ().Затем вы можете использовать эту отслеживаемую группу с \1 (вторая группа будет \2 и т. Д.).

sed "s/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\)/'\1'/g"

Обратите внимание на g в конце, что гарантирует замену всех совпадений (еслив одной строке более одного).


Если вы добавите -r к значению sed, неловкие обратные слеши перед () могут быть опущены:

sed -r "s/([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9])/'\1'/g"

Это можно еще больше упростить с помощью квантификаторов:

sed -r "s/([0-9]{4}-[0-9]{2}-[0-9]{2})/'\1'/g"

Или даже:

sed -r "s/([0-9]{4}-([0-9]{2}){2})/'\1'/g"

Как уже упоминалось в комментариях: Кроме того, в данном конкретном случае вы можете использовать& вместо \1, что соответствует всему искомому выражению, и пропустите ():

sed -r "s/[0-9]{4}(-[0-9]{2}){2}/'&'/g"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...