Как заменить второй шаблон (точка) после шаблона (запятая) в Bash - PullRequest
1 голос
/ 02 ноября 2019

Как заменить вторую точку после запятой.

это самое близкое, что я мог пройти

echo '0.592922148,0.821504176,1.174.129.731' | xargs -d ',' -n1 echo | sed 's/\([^\.]*\.[^\.]*\)\./\1/' | sed 's/\([^\.]*\.[^\.]*\)\./\1/'

Вывод:

0.592922148
0.821504176
1.174129731

Ожидаемый вывод:

0.592922148,0.821504176,1.174129731

Ответы [ 4 ]

3 голосов
/ 02 ноября 2019

Вы можете использовать

sed -e ':a' -e 's/\(\.[^.,]*\)\./\1/' -e 't a'

См. онлайн sed демо :

s='0.592922148,0.821504176,1.174.129.731'
sed -e ':a' -e 's/\(\.[^.,]*\)\./\1/' -e 't a' <<< "$s"

Подробности

  • :a - метка a
  • s/\(\.[^.,]*\)\./\1/ - находит и фиксирует в группе 1 точку, затем любые 0+ символов, кроме точки и запятой, а затем просто совпадает с точкой и заменяетэто соответствует значению в группе 1 (таким образом, удаляя вторую совпадающую точку)
  • t a - если произошла успешная замена, возвращается к позиции метки a в строке.
2 голосов
/ 02 ноября 2019

Хотя я думаю, что решение sed - ваш лучший выбор, поскольку вы пометили свой вопрос как sed и awk, решение awk довольно простое, также с использованием split() и базовой строкиконкатенации. (только не так коротко) Например, вы можете сделать:

awk -v OFS=, -F, '{
    for (i=1; i<=NF; i++) {
        n=split ($i, a,".")
        if (n > 2) {
            s=a[1] "." a[2]
            for (j=3; j<=n; j++)
                s = s a[j]
            $i=s
        }
    }
}1'

Где вы определяете разделитель полей и разделители полей вывода как ','. Затем зацикливаясь на каждом поле, проверьте возвращаемое значение split(), разбив поле на массив на '.' на массив a. Если полученное количество элементов превышает 2, соберите вместе первые два элемента, восстановив первый '.' в числе, а затем просто объедините оставшиеся поля. 1 в конце - это «печать по умолчанию» для печати обновленной записи.

Пример использования / Вывод

$ echo '0.592922148,0.821504176,1.174.129.731' |
> awk -v OFS=, -F, '{
>     for (i=1; i<=NF; i++) {
>         n=split ($i, a,".")
>         if (n > 2) {
>             s=a[1] "." a[2]
>             for(j=3;j<=n;j++)
>                 s = s a[j]
>             $i=s
>         }
>     }
> }1'
0.592922148,0.821504176,1.174129731
1 голос
/ 02 ноября 2019

Не могли бы вы попробовать следующее.

echo '0.592922148,0.821504176,1.174.129.731' | 
awk '
BEGIN{
  FS=OFS=","
}
{
  for(i=1;i<=NF;i++){
    ind=index($i,".")
    if(ind){
      val1=substr($i,1,ind)
      val2=substr($i,ind+1)
      gsub(/\./,"",val2)
      $i=val1 val2
    }
  }
  val1=val2=""
}
1' 


Объяснение: Добавление пояснения к приведенному выше коду.

echo '0.592922148,0.821504176,1.174.129.731' |   ##Printing values as per OP mentioned and using pipe to send its output as standard input for awk command.
awk '                                            ##Starting awk program from here.
BEGIN{                                           ##Starting BEGIN section of this program here.
  FS=OFS=","                                     ##Setting FS and OFS as comma for each line of Input_file here.
}                                                ##Closing BEGIN BLOCK here.
{
  for(i=1;i<=NF;i++){                            ##Starting a for loop to traverse through fields of line..
    ind=index($i,".")                            ##Checking index of DOT in current field and saving it into ind variable.
    if(ind){                                     ##Checking condition if variable  ind is NOT NULL.
      val1=substr($i,1,ind)                      ##Creating variable val1 from sub-string in current field from 1 to ind value.
      val2=substr($i,ind+1)                      ##Creating variable val2 from sub-string in current field from ind+1 value to till complete length of current field.
      gsub(/\./,"",val2)                         ##Globally substituting DOTs with NULL in val2 variable.
      $i=val1 val2                               ##Re-crearing current field with value of val1 val2.
    }                                            ##Closing BLOCK for if condition.
  }                                              ##Closing BLOCK for for loop.
  val1=val2=""                                   ##Nullifying val1 and val2 variables here.
}                                                ##Closing main code BLOCK here.
1'                                               ##Mentioning 1 will print edited/non-edited line.
1 голос
/ 02 ноября 2019

An awk verison:

echo '0.592922148,0.821504176,1.174.129.731' | awk  -F, '{for (i=1;i<=NF;i++) {sub(/\./,"#",$i);gsub(/\./,"",$i);sub(/#/,".",$i);print $i}}'
0.592922148
0.821504176
1.174129731

Делит строку inn на несколько полей на ,. Затем замените сначала . на #. Затем замените остаток . на ничто. Последний замените # обратно на . и распечатайте его.

Редактировать

awk -F, '{for (i=1;i<=NF;i++) {sub(/\./,"#",$i);gsub(/\./,"",$i);sub(/#/,".",$i);a=a (i==1?"":",")$i}print a}' file
0.592922148,0.821504176,1.174129731
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...