2009-09-10 3 views
76

Я новичок в sed и awk - поэтому я не уверен, что это самый эффективный способ сделать это.Извлечение первых двух символов строки (Shell Scripting)

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

Возьмите n позиций этой строки из этой более крупной строки x.

IE.

 
USCAGoleta9311734.5021-120.1287855805 = US 
+3

Спасибо всем. Я закончил тем, что использовал «cut -c1-2», честно говоря, я даже не знал, что там был «разрез». Я бы хотел сказать, что я довольно опытный в командной строке, но, видимо, мне есть чему поучиться. – Greg

+1

@Greg, просто имейте в виду, что разрез выполняется как отдельный процесс - он будет медленнее, чем внутреннее решение bash, которое я разместил рядом с ним в своем ответе. Это не будет иметь никакого значения, если вы не обрабатываете огромные наборы данных, но вы должны помнить об этом. – paxdiablo

+0

[Изменить] На самом деле, я думаю, что эта строка кода, вероятно, будет выполнена около 50 000 раз за отчет. Поэтому я могу просто пойти с внутренним методом Bash, который, как вы сказали, сохранит некоторые необходимые ресурсы. – Greg

ответ

29

Самый простой способ

${string:position:length} 

Где это извлекает $length подстроку из $string в $position.

Это bash builtin, поэтому awk или sed не требуется.

+0

Это короткий, сладкий и самый простой способ получить подстроку. – user1336087

108

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

pax> long="USCAGol.blah.blah.blah" 
pax> short="${long:0:2}" ; echo "${short}" 
US 

Это установит short как первые два символа long. Если long короче двух символов, то short будет идентичен ему.

Этот метод в оболочке обычно лучше, если вы собираетесь делать это много (например, 50 000 раз за отчет, как вы упоминаете), поскольку накладные расходы на процесс отсутствуют. Все решения, которые используют внешние программы, будут страдать от этих накладных расходов.

Если вы также хотели, чтобы обеспечить минимальную длину, вы могли бы подушечка его, прежде чем руки что-то вроде:

pax> long="A" 
pax> tmpstr="${long}.." 
pax> short="${tmpstr:0:2}" ; echo "${short}" 
A. 

Это обеспечило бы что-нибудь менее двух символов в длину был проложенный по праву с периодами (или чем-то еще, просто путем изменения символа, используемого при создании tmpstr). Непонятно, что вам это нужно, но я думал, что поставлю его для полноты.


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

short=$(echo "${long}" | cut -c1-2) 
short=$(echo "${long}" | head -c2) 
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}' 
short=$(echo "${long}" | sed 's/^\(..\).*/\1/') 

Первые два (cut и head) идентичны для однострочной строки - они в основном оба просто вернут вам первые два символа. Они отличаются тем, что cut даст вам первые два символа каждой строки и head даст вам первые два символа всего ввода

Третий использует функцию awk подстроки извлечь первые два символа и четвертый использует sed группы захвата (используя () и \1), чтобы захватить первые два символа и заменить всю их линию.Они оба похожи на cut - они доставляют первые два символа каждой строки на входе.

Ничего из этого не имеет значения, если вы уверены, что ваш вход является одной строкой, все они имеют одинаковый эффект.

0

Это что вы после?

my $string = 'USCAGoleta9311734.5021-120.1287855805'; 

my $first_two_chars = substr $string, 0, 2; 

исй: substr

+1

, учитывая, что он, вероятно, будет называть это из оболочки, лучшей формой будет 'perl -e 'print substr $ ARGV [0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'' –

0

если MyString = USCAGoleta9311734.5021-120.1287855805

print substr(mystring,0,2) 

напечатает США

где 0 является начальным положением и 2, как мэны символов читать

+0

Скажите .. .Это не GW-BASIC? О, подождите, это 'awk'. Извините, я не мог сказать сначала. –

0
perl -ple 's/^(..).*/$1/' 
+0

Вы забыли повторить строку. –

+0

Нет, я не ... это читает STDIN – dsm

29

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

echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}' 

и

echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/' 

awk один должен быть достаточно очевидно, но вот объяснение sed одного:

  • заменить «s /»
  • группа «()» двух любых символов «..», начинающихся с начала строки «^» и сопровождаемых любым символом ».«повторяющиеся ноль или более раз» * »(обратные косые черты необходимы для выхода из некоторых специальных символов)
  • «/»содержимое первой (и только в этом случае) группы (здесь обратная косая черта - это специальная бежать со ссылкой на подвыражении соответствия)
  • сделано «/»
3

colrm - удалить столбцы из файла

чтобы оставить первые два символа, просто удалить столбцы, начиная с 3

cat file | colrm 3 
3

Если вы в bash, вы можете сказать:

bash-3.2$ var=abcd 
bash-3.2$ echo ${var:0:2} 
ab 

Это может быть только то, что вам нужно ...

+1

Извините - я не видел, что Pax уже разместил это. –

+0

Самый простой и простой ответ! работал как шарм – aloha

3

Довольно поздно, действительно, но здесь это

sed 's/.//3g' 

Или

awk NF=1 FPAT=.. 

или

perl -pe '$_=unpack a2' 
3

Просто Grep:

echo 'abcdef' | grep -Po "^.."  # ab 
1

Если ваша система использует другую оболочку (не bash), но ваша система имеет bash, то вы можете использовать присущую строку манипуляции bash, вызывая bash с переменной:

strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest 
bash -c "str=\"$strFull\";$strEcho;" 
+0

Используется тот же метод, что и [главный ответ] (http://stackoverflow.com/a/1405641/393280), только вызывая 'bash', если вы еще не используете его. – palswim

+0

К сожалению, это связано со всеми накладными расходами на вызов другого процесса, но иногда это накладные расходы не имеет значения, как простота и знакомость. – palswim