как изменить только один символ в строке, если таких символов несколько?

GNU parallel — это инструмент, который вам нужен. Автор, Оле Танге , здесь завсегдатай и написал несколько хороших ответов на вопросы об этом

.

Версия GNU xargsиз findutilsтакже имеет некоторые возможности для параллельного выполнения нескольких заданий. Вероятно, его проще использовать для простых задач, подобных вашей, но он далеко не так гибок и эффективен, как parallel.

Например:

find. -maxdepth 1 -type f -name 'a_file_*' -print0 | 
  xargs -0r -L 1 -P 4 sh -c '/usr/bin/md5sum "$1" > "$1.md5sum"' {}

Будет запущено до 4 md5sumзаданий параллельно(-P 4). Я также использовал опцию -L 1, чтобы ограничить каждое задание обработкой одного имени файла за раз -без этого (, иначе было бы запущено только 1 задание с 1000 именами файлов)

2
17.11.2019, 00:03
3 ответа

Заголовок ("Как мне изменить только один символ в строке, если таких символов несколько?" )- это ваша попытка решения, но фактическая проблема объясняется в теле вопроса. Сравните XY задачу . Мой ответ касается тела.


IFS=- read n1 n2 n3

Это заполнит переменные n1, n2и n3фрагментами пользовательского ввода; соответственно:

  • перед первым -,
  • между первым -и вторым -,
  • после второго -(, включая оставшиеся -символы, если таковые имеются ).

Затем вы можете использовать printf, чтобы распечатать их в любом формате, например, в формате.

printf '(%s) %s-%s\n' "$n1" "$n2" "$n3"
printf '%s%s%s\n' "$n1" "$n2" "$n3"

Вы можете быть либеральными в том, что вы принимаете и не требовать строгого формата. Пример в качестве функции оболочки:

get_phone_number() {
   IFS= read -rp "Enter phone number (10 digits; additional dashes, spaces, whatever allowed): " p || return 1
   # remove non-digits
   p="$(tr -dc '0123456789' <<< "$p")"
   # check if there is 10 of them
   if [ "${#p}" -ne 10 ]; then
      echo "Wrong number of digits. Aborting." >&2; return 2
   else
      n1="${p:0:3}"
      n2="${p:3:3}"
      n3="${p:6:4}"
   fi
}

Вызвать get_phone_number. Если функция выполнена успешно, используйте $n1, $n2и $n3с printf(, как указано выше ), или любым другим способом.

5
27.01.2020, 21:50

Вы понимаете, что создаете файл с именем phone, верно? Также бессмысленно связывать echoс cat, вы могли бы (, но не должны )просто делатьecho "$phone" > phone


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

.
#!/bin/bash

read -rp "Enter phone number (xxx-xxx-xxxx): " p

area_code=${p:0:3}
prefix=${p:4:3}
line=${p:8:4}

printf '%s\n%s\n' \
"($area_code) ${prefix}-${line}" \
"${area_code}${prefix}${line}"

Чтение может предложить пользователю ввести данные, чтобы мы могли исключить комбинацию echo/ read.
Затем мы используем расширение параметра , чтобы извлечь три части телефонного номера и распечатать их в двух требуемых форматах.

Обратите внимание, :это не выполняет никакой проверки работоспособности, поэтому пользователи могут вводить ложные данные и получать фиктивные выходные данные.

2
27.01.2020, 21:50

GNU sedпозволяет указать, какое вхождение шаблона (в строке )следует заменить:

Первый (по умолчанию)

echo AAAAA | sed 's/A/X/'
XAAAA

Все

echo AAAAA | sed 's/A/X/g'
XXXXX

я -й

echo AAAAA | sed 's/A/X/3'
AAXAA

Чтобы конкретно решить вашу проблему с помощью этого метода, вам потребуются две модификации вsed:1 )изменить начало строки (^), чтобы добавить открывающие круглые скобки, 2 )заменить первый тире на закрывающие скобки и пробел.

echo 123-123-1234 | sed 's/^/(/;s/-/) /'
(123) 123-1234

В качестве альтернативы, sedпозволяет сопоставлять шаблоны и сохранять их (по количеству вхождений ), заключая шаблон в круглые скобки. В выходной строке вы можете называть их по номеру:

echo 123-123-1234 | sed 's/\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)/(\1) \2-\3/'
(123) 123-1234

Здесь [0-9]соответствует цифре от 0 до 9,\+означает одно или несколько вхождений предыдущей группы (Расширение GNU дляsed\(<pattern>\)сохранит шаблон и присвоит ему порядковый номер (, начиная с 1 для первого и так далее ). Таким образом, \([0-9]\+\)-будет соответствовать одной или нескольким цифрам, за которыми следует тире, и запомнит цифровую часть.

В выводе \1печатается первый сохраненный шаблон из совпадения (, т.е. [0-9]\+... одна или несколько цифр перед тире. Затем мы просто используем три сохраненные группы цифр и форматируем их по своему усмотрению.

3
27.01.2020, 21:50

Теги

Похожие вопросы