AppleScript: Como extrair seção da string (com base em caracteres definidos)?

3

Exemplo:

set theText to "I ate an apple at 11:54 pm without the skin."

Eu gostaria theTimede ser uma string que contém o texto:11:54

Portanto, gostaria que o delimitador do item de texto de abertura fosse at_e o delimitador do item de texto de fechamento fosse um _pmou outro _am, dependendo do período existente na string. (Observação - todas as instâncias de um sublinhado nesta postagem representam um espaço porque não consigo representar um espaço na formatação do código do Stack Exchange.)

O conteúdo de theTextvariará bastante. Por exemplo, pode ser:

set theText to "I ate two navel oranges at 6:30 am with a glass of water."

Mas o formato da hora sempre permanecerá constante. O horário sempre será precedido por um "at" e esse "at" será sempre a primeira instância de um "at" na string. Da mesma forma, o tempo será necessariamente seguido por "sou" ou "pm".

esfera de rubik
fonte
Atualizei minha resposta original para incluir um espaço antes e depois dos três separadores de campo (delimitadores) "at", "sou" e "pm", pois faz mais sentido fazê-lo e não apenas um espaço como originalmente escrito.
user3439894
Atualizei minha resposta novamente para mostrar como uma única linha de código AppleScript comum faz o que as 8 linhas de código AppleScript puro fazem na outra resposta.
user3439894
Bom obrigado. No entanto, percebi que realmente prefiro sua solução original porque é mais restritiva, pois abordou exatamente minha pergunta original com uma interpretação literal (como você observou). Em geral, eu gosto de fazer o mínimo de suposições possível quando estou escrevendo código, para ser conservador. Embora possa não ser comum ou esperado, dois pontos podem existir antes do tempo na theTextstring, o que desorientaria um método de obtenção baseado em dois pontos theTime.
Rubik's sphere

Respostas:

3

Executando o seguinte código AppleScript no AppleScript Editor:

set theText to "I ate an apple at 11:54 pm without the skin."
set theTime to do shell script "awk -F ' at | am | pm ' '{print $2}'<<<" & quoted form of theText
log "The time was: " & theTime

set theText to "I ate two navel oranges at 6:30 am with a glass of water."
set theTime to do shell script "awk -F ' at | am | pm ' '{print $2}'<<<" & quoted form of theText
log "The time was: " & theTime

Produz a seguinte saída no log de eventos do AppleScript Editor:

tell current application
    do shell script "awk -F ' at | am | pm ' '{print $2}'<<<'I ate an apple at 11:54 pm without the skin.'"
        --> "11:54"
    (*The time was: 11:54*)
    do shell script "awk -F ' at | am | pm ' '{print $2}'<<<'I ate two navel oranges at 6:30 am with a glass of water.'"
        --> "6:30"
    (*The time was: 6:30*)
end tell

Nos exemplos acima eu defini os separadores de campo (delimitadores) em awkutilizando a -F opção como ' at | am | pm 'o que equivale a "at", "am" e "pm" e imprime '{print $2}'o que há entre os separadores de campo .

Nota: O uso do log comando não é necessário para a codificação da resposta e está sendo usado apenas para mostrar qual o valor de theTimepara a saída do Log de Eventos, além do que é mostrado a seguir -->, que é o resultado normalmente mostrado no Log de Eventos .


Atualização: eu escrevi minha resposta original com base em uma interpretação literal, quando disse: " Então, eu gostaria que o delimitador de item de texto de abertura fosse at_e o delimitador de item de texto de fechamento fosse um _pmou outro_am ", o que se queria era usar literalmente aqueles como os delimitadores. No entanto, como uma solução diferente usando código AppleScript puro , em uma resposta separada, foi apresentada, deixe-me apresentar uma solução de código AppleScript de uma linha que faz a mesma coisa que as 8 linhas de código AppleScript puro e com foco nos dois pontos , mas como parte de uma representação RegEx do tempo em horas e minutos.

set theTime to do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<" & quoted form of theText

Executando o seguinte código AppleScript no AppleScript Editor:

set theText to "I ate an apple at 11:54 pm without the skin."
set theTime to do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<" & quoted form of theText

set theText to "I ate two navel oranges at 6:30 am with a glass of water."
set theTime to do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<" & quoted form of theText

Produz a seguinte saída no log de eventos do AppleScript Editor:

tell current application
    do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<'I ate an apple at 11:54 pm without the skin.'"
            --> "11:54"
    do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<'I ate two navel oranges at 6:30 am with a glass of water.'"
            --> "6:30"
end tell

Como você pode ver, se há um ou dois números precedendo os dois pontos, o RegEx corresponde e o awk programa retorna a correspondência desejada, sendo a hora atual.

Pessoalmente, eu escolheria usar esse método específico sobre minha resposta original, pois é um método melhor nessas circunstâncias e ou sobre o código AppleScript puro , pois não posso justificar a escrita de 8 linhas de código AppleScript puro quando uma única linha de código AppleScript normal produz os mesmos resultados que as 8 linhas!

user3439894
fonte
2

Você pode fazer isso com AppleScript puro, mesmo que o método de script de shell apresentado acima seja muito bom:

set theText to "I ate an apple at 11:54 pm without the skin."
set the_colon_location to offset of ":" in theText
-- now we know where the colon is.
-- The Time is going to be on either side of it.
set the_starting_point to the_colon_location - 2
set the_ending_point to the_colon_location + 5
set the_time_string to characters the_starting_point thru the_ending_point of theText as string
-- in case the hour is not two digits, the first character will be a space
if character 1 of the_time_string is " " then
    set the_time_string to characters 2 thru -1 of the_time_string as string
end if
return the_time_string
Christian Boyce
fonte
É sempre bom saber fazer a mesma coisa de maneiras diferentes, mas quando set theTime to do shell script "awk 'match($0,/[0-9]{1,2}:[0-5][0-9]/) {print substr($0,RSTART,RLENGTH)}'<<<" & quoted form of theTextproduz os mesmos resultados em uma linha de código AppleScript comum que leva 8 linhas do seu código AppleScript puro para fazer, não acredito que jamais usaria seu método No entanto, eu o adicionei ao meu arquivo de trechos de código para ter um exemplo do fluxo lógico, caso eu encontre um motivo convincente para usá-lo em uma solução. awk
user3439894
1
Totalmente entendido. No entanto, minha resposta não foi feita para competir na velocidade ou na contagem de linhas. Era para ser legível e compreensível pelo maior número de pessoas possível. Eu tiro meu chapéu completamente para o uso de expressões regulares na outra solução.
Christian Boyce