Na przykład, biorąc pod uwagę:
USCAGoleta9311734.5021-120.1287855805
Chcę tylko wyodrębnić:
US
Na przykład, biorąc pod uwagę:
USCAGoleta9311734.5021-120.1287855805
Chcę tylko wyodrębnić:
US
Odpowiedzi:
Prawdopodobnie najbardziej wydajną metodą, jeśli używasz bash
powłoki (i wydaje się, że tak jest, na podstawie twoich komentarzy), jest użycie wariantu podłańcucha rozwijania parametrów:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Będą short
to pierwsze dwa znaki long
. Jeśli long
jest krótszy niż dwa znaki, short
będzie identyczny.
Ta metoda w powłoce jest zwykle lepsza, jeśli zamierzasz to robić dużo (np. 50000 razy na raport, jak wspomniałeś), ponieważ nie ma narzutu związanego z tworzeniem procesu. Wszystkie rozwiązania korzystające z programów zewnętrznych będą cierpieć z powodu tego obciążenia.
Jeśli chcesz również zapewnić minimalną długość, możesz wyłożyć ją przed ręką za pomocą czegoś takiego:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Zapewniłoby to, że cokolwiek o długości mniejszej niż dwa znaki zostało dopełnione po prawej stronie kropkami (lub czymś innym, po prostu zmieniając znak używany podczas tworzenia tmpstr
). Nie jest jasne, czy tego potrzebujesz, ale pomyślałem, że wstawię to dla kompletności.
Powiedziawszy to, istnieje wiele sposobów, aby to zrobić za pomocą programów zewnętrznych (na przykład, jeśli nie masz bash
dostępnych), z których niektóre to:
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/')
Pierwsze dwa ( cut
i head
) są identyczne dla ciągu jednowierszowego - w zasadzie oba zwracają po prostu pierwsze dwa znaki. Różnią się tym, cut
że dadzą ci pierwsze dwa znaki w każdej linii i head
dadzą ci pierwsze dwa znaki z całego wejścia
Trzecia używa funkcji awk
podłańcucha do wyodrębnienia pierwszych dwóch znaków, a czwarta używa sed
grup przechwytywania (przy użyciu ()
i \1
) do przechwycenia pierwszych dwóch znaków i zastąpienia nimi całego wiersza. Oba są podobne cut
- dostarczają pierwsze dwa znaki z każdego wiersza na wejściu.
Nic z tego nie ma znaczenia, jeśli masz pewność, że dane wejściowe to jedna linia, wszystkie mają identyczny efekt.
printf '%s'
zamiast echo
w przypadku istnieją dziwne znaki w ciągu: stackoverflow.com/a/40423558/895245 Dla POSIX obsesję: head -c
nie POSIX, cut -c
a awk substr
to, sed \1
nie jestem pewien.
najłatwiej jest
${string:position:length}
Gdzie to wyodrębnia $length
podciąg z $string
at $position
.
Jest to wbudowana funkcja bash, więc awk lub sed nie są wymagane.
Musisz zdobyć kilka dobrych odpowiedzi i pójdę z Basha wbudowane siebie, ale skoro pytasz o sed
a awk
i ( prawie ) nikt inny nie zaproponował rozwiązania oparte na nich, ofiaruję Ci te:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
i
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
To awk
powinno być dość oczywiste, ale oto wyjaśnienie sed
jednego:
substr($0,1,2)
.
Jeśli jesteś w środku bash
, możesz powiedzieć:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
To może być właśnie to, czego potrzebujesz…
Po prostu grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
opcję, aby ją skrócić. Wszystkie wyrażenia regularne będą rozumieć ten wzorzec.
Możesz użyć printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Dość późno, ale oto jest
sed 's/.//3g'
Lub
awk NF=1 FPAT=..
Lub
perl -pe '$_=unpack a2'
Jeśli chcesz używać skryptów powłoki i nie polegać na rozszerzeniach innych niż posix (takich jak tak zwane bashizmy), możesz użyć technik, które nie wymagają rozwidlania zewnętrznych narzędzi, takich jak grep, sed, cut, awk itp., sprawić, że twój skrypt będzie mniej wydajny. Może wydajność i przenośność Posix nie są ważne w twoim przypadku użycia. Ale jeśli tak jest (lub po prostu jest to dobry nawyk), możesz użyć następującej metody opcji rozwijania parametrów , aby wyodrębnić pierwsze dwa znaki zmiennej powłoki:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Wykorzystuje rozwinięcie parametrów „najmniejszy prefiks” w celu usunięcia pierwszych dwóch znaków (to jest ${var#??}
część), a następnie rozwinięcie parametrów „najmniejszy sufiks” ( ${var%
część) w celu usunięcia tego ciągu składającego się wyłącznie z dwóch pierwszych znaków z oryginału wartość.
Ta metoda została wcześniej opisana w odpowiedzi na pytanie „Powłoka = Sprawdź, czy zmienna zaczyna się od #”. Ta odpowiedź opisuje również kilka podobnych metod rozwijania parametrów, których można użyć w nieco innym kontekście niż ten, który odnosi się do pierwotnego pytania.
Jeśli twój system używa innej powłoki (nie bash
), ale twój system ma bash
, możesz nadal używać nieodłącznej manipulacji ciągiem bash
, wywołując bash
zmienną:
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;"
bash
wtedy, gdy jeszcze jej nie używasz.
Dla zabawy dodam jeszcze kilka, że choć są zbyt skomplikowane i bezużyteczne, nie zostały wymienione:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
jeśli mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
wydrukowałoby US
gdzie 0 to pozycja początkowa, a 2 to jak odczytać wiele znaków
awk
. Przepraszam, na początku nie mogłem powiedzieć.
Czy to jest to, czego szukasz?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'