Wie lösche ich eine bestimmte Zeile eines Absatzes in AppleScript, während das ursprüngliche Format des Textes beibehalten wird?

Ich habe eine Textvariable der Klasse text, die so etwas anzeigt, wenn sie zurückgegeben wird:

"
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

Ich möchte in der Lage sein, bestimmte Zeilen aus dem Text zu löschen, ohne den Rest der Variablen zu beeinflussen.

Zum Beispiel: delete {1, 3}um dieses Ergebnis zu erhalten:

"This is sentence 1.
This is sentence 3.
This is sentence 4."

Die in dieser Antwort beschriebene Methode hat einen schwerwiegenden Fehler:

"Wie lösche ich eine bestimmte Zeile eines Absatzes in AppleScript?"

Die verknüpfte Methode zum Löschen von Zeilen in einem Absatz konvertiert tatsächlich alle Zeilenvorschübe in der Textvariablen in Zeilenumbrüche. Mit anderen Worten, es ist unmöglich, diesen Code mehr als einmal für dieselbe Variable auszuführen.

Zum Beispiel der folgende Code:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."
set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText
-- Employing the same method on the same variable:
set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText
return varText

kehrt zurück

""

Da diese Methode nur korrekt funktioniert, wenn die Zeilen der Textvariablen das Produkt von a sind linefeed(wie es sollte), besteht das Problem nichtreturn darin, dass diese Methode a nicht als neue Zeile wahrnimmt (wie ich ursprünglich in dieser Frage behauptet hatte). Das Problem ist, dass dieser Code returnüberhaupt erst ein in die Textvariable einführt.


Daher möchte ich eine Lösung, mit der ich dieselbe Textvariable mehr als einmal in demselben AppleScript durch die Lösung ausführen kann.

Mit anderen Worten, ich suche nach einer Methode, um eine bestimmte Zeile aus einem Absatz zu entfernen, die diesen Fehler nicht aufweist und nirgendwo returnim Text ein einfügt.

Bezüglich der Informationen in Ihrer Bearbeitung: Der do shell script "sed ..." Befehl, wenn er im Terminal ausgeführt wird, gibt mit (x0A) nicht (x0D) varTextzurück , wie es sein soll. Sogar der kompilierte Befehl im Skripteditor hat immer noch (x0A) nicht (x0D), aber warum er mit (x0D) Absicht des erwarteten (x0A) zurückgegeben wird, ist mir im Moment ein Rätsel. Ich werde dies als AppleScript-Fehler betrachten, da es nicht das erwartete Verhalten desselben widerspiegelt, wenn es in Terminal ausgeführt wird. Aus diesem Grund habe ich meine Antwort gelöscht, weil mir das Problem nicht bewusst war. \n\rdo shell script "sed ..." \n\r\r\n
GrahamMiln Seitdem ich den Fehler mit der ursprünglichen Antwort identifiziert habe, die mich dazu veranlasst hat, die zweite Frage zu posten, ist es möglich, diese beiden Fragen zusammenzuführen? Wenn nicht, können Sie diese Frage einfach ganz löschen, da @ user3439894 ihre aktualisierte Antwort auf die zweite Frage gegeben hat?
Ich möchte diese Frage nicht selbst löschen, da dies zu einer Verwarnung gegen mein SE-Konto führen würde. (Ich verstehe, dass das Löschen der eigenen Frage bestraft wird).
In Bezug auf die Verwendung von returnstimme ich natürlich zu! In Wirklichkeit verwende und habe ich nie verwendet , um mehrzeilige Zeichenfolgen zu verketten! Aus diesem Grund musste ich den Titel und den Text dieser Frage erheblich bearbeiten. mein Beitrag enthielt mehrere ungenaue Aussagen. Dieser Beitrag wurde zum ersten Mal veröffentlicht , bevor ich den Fehler in Ihrem Code aufgegriffen hatte, der (wie mir schließlich klar wurde) erklärte, woher all die Variablen in meinem Text kamen! Ich hatte ursprünglich angenommen, dass ich – irgendwie – für die Verbreitung der Charaktere verantwortlich sei, was, wie ich jetzt weiß, nicht der Fall ist. returnreturnsreturn
Zunächst einmal war es nicht mein Code per se, der den Fehler hatte! Es ist ein Fehler darin, wie der do shell script Befehl verarbeitet, was von der Befehlszeile zurückgegeben wird , es ist AppleScript, das die Ausgabe der Befehle, die innerhalb des do shell script Befehls ausgeführt werden, nicht richtig verarbeitet ! Ihre Verwendung returnals mehrzeilige Zeichenfolgenverkettung war ein Problem, da sedder Inhalt der Variablen als eine Zeile angezeigt und gelöscht wurde, da x0Akeine x0DZeilenenden erwartet werden. Wie auch immer, meine aktualisierte Antwort behandelt sowohl die schlechte Verwendung von returnover linefeedals auch den Fehler.
Ja, ich wollte offensichtlich nicht andeuten, dass Sie persönlich verantwortlich sind :). Als ich „Fehler in Ihrem Code“ sagte, war das eine Abkürzung für „den AppleScript-Fehler, der sich in der von Ihnen bereitgestellten Lösung manifestierte“. Sie schrieben: "Ihre Verwendung von return als mehrzeilige Zeichenfolgenverkettung war ein Problem." Wie ich bereits sagte, habe ich das vorliegende Problem völlig missverstanden (da ich den AppleScript-Fehler nicht erkannt habe), als ich dieses Beispiel für die Verwendung returnzum Verketten im ursprünglichen Beitrag bereitgestellt habe.
Ich habe nicht ein einziges Mal in meinem ganzen Leben tatsächlich returnan Verkettungen gewöhnt; Dieses Beispiel diente dazu, ein Problem hervorzuheben, das eigentlich gar nicht das Problem war. Unabhängige Frage ... hatten Sie Gelegenheit, meine Beobachtung zu Grahams Antwort zu bestätigen?
Okay, ich habe mit seinem Code gespielt und es sieht so aus, als würde er nicht so funktionieren, wie Sie es möchten, selbst wenn Sie alle bis auf die letzte returndurch ersetzen linefeedoder die andere Methode zum Festlegen der Variablen verwenden. Ich werde morgen mal genauer hinschauen, da ich für die Nacht fertig bin. Wie auch immer, meine Antwort verwendet eine Fehlerbehebung und kann verarbeiten return, wenn sie als spezielle Zeichenfolgenkonstante der Textklasse verwendet wird und / oder was vom do shell scriptBefehl zurückgegeben wird.

Antworten (3)

Okay, ich habe das Original und die erste Bearbeitung gelöscht, weil Sie Ihre ursprüngliche Frage so weit bearbeitet haben, dass es einfacher ist, insgesamt eine neue Antwort zu schreiben.

Da Ihre ursprüngliche Frage die folgende Codezeile zeigte , werde ich sie als Beispiel dafür, wie die Variable gesetzt werden kann, einfügen, um Folgendes zu sagen.

Ob die varTextgesetzt wurde von zB:

set varText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")
  • In which returnis x0Dvs. the richtiger use of linefeed( x0A) Stattdessen in einem Fall, in dem die Variable Daten und keine Wegwerfnachricht ist.

Oder:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."
  • Wobei jede dieser Zeilen tatsächlich mit einem linefeed( x0A) endet, wie es auf einem Mac sein sollte.

Der do shell script Befehl hat einen Fehler , da er nach dem, was von der Befehlszeile zurückgegeben wird, konvertiert wird x0A, x0Dwobei die erwarteten x0AEndungen zurückgegeben werden. Ich habe dies bestätigt, denn wenn ich Folgendes verwende:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText & " | tee $HOME/Desktop/outfile"

outfileEnthält dann linefeed( x0A) Endungen, so dass dasselbe zurückgegeben wird, do shell scriptaber es konvertiert dann fälschlicherweise die x0AZeilenenden in x0DEndungen, die dann wie folgt behandelt werden können:

Um den Fehler zu berücksichtigen, stellen Sie also immer sicher, dass der Inhalt der übergebenen und zurückgegebenen Variablen x0AZeilenenden enthält, indem Sie den folgenden handlerund Beispielcode verwenden .

Im Folgenden wird davon ausgegangen, dass dies varTextbereits durch eine der oben beschriebenen Methoden festgelegt wurde.

on ensureLinesEndWith0A(varText)
    set varText to paragraphs of varText
    set oldTID to AppleScript's text item delimiters
    set AppleScript's text item delimiters to linefeed
    set varText to varText as string
    set AppleScript's text item delimiters to oldTID
    return varText
end ensureLinesEndWith0A

set varText to ensureLinesEndWith0A(varText)
set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText
set varText to ensureLinesEndWith0A(varText)

Sie könnten dann erneut Folgendes verwenden, um weitere Zeilen aus zu löschen varText:

set varText to ensureLinesEndWith0A(varText)
set varText to do shell script "sed  -e '1d;3d' <<< " & quoted form of varText
set varText to ensureLinesEndWith0A(varText)

Das folgende Bild zeigt ein Beispiel für den zweimaligen Aufruf des do shell script " sed ..." Befehls .

Bild des Codebeispiels

@rubiks Sphäre, sehen Sie sich das Bild an, das ich meiner Antwort hinzugefügt habe.
Ich habe deinen Workaround getestet text item delimiters to linefeed. Ich glaube, dass es erfolgreich den schädlichen kleinen AppleScript-Fehler behebt, den wir identifiziert haben. Ich kann jetzt unzählige do shell script "sed -e...Operationen auf dieselbe Textvariable innerhalb desselben Skriptlaufs ausführen, und die angegebenen Zeilen werden wie beabsichtigt zuverlässig gelöscht. Ich danke Ihnen für Ihre Hilfe!

Beispiel:

set varText to "
This is sentence 1.
This is sentence 2.
This is sentence 3.
This is sentence 4."

set varText to do shell script "sed -e '1d;3d' <<< " & quoted form of varText

Kehrt zurück:

"This is sentence 1.
This is sentence 3.
This is sentence 4."

Update: Als Ergebnis einer Entdeckung, die in Edit: of How to delete a specific line of a “return”-based paragraph in AppleScript erwähnt wurde? , lassen Sie mich folgende Aussage treffen:

HINWEIS: Leider enthält das, was in diesem Fall zurückgegeben wird, Wagenrücklaufzeichen (x0D) anstelle der erwarteten Zeilenumbruchzeichen (x0A) und ist meiner Meinung nach ein Fehler !

Es ist ein Fehler, weil: Der do shell script "sed ..." Befehl , wenn er im Terminal damit ausgeführt wird, mit (x0A) nicht (x0D) varTextzurückgibt , wie es sollte. Sogar der kompilierte Befehl im Skripteditor hat immer noch (x0A) nicht (x0D), aber warum er mit (x0D) Absicht des erwarteten (x0A) zurückgegeben wird, ist mir im Moment ein Rätsel und ich werde dies als AppleScript betrachten Fehler, da es nicht das erwartete Verhalten desselben widerspiegelt, wenn es im Terminal ausgeführt wird.\n\rdo shell script "sed ..." \n\r\r\n

Um den Fehler in den Ergebnissen des do shell script "sed ..." Befehls zu berücksichtigen , würde ich folgendermaßen damit umgehen. Verwenden Sie nach dem do shell script "sed ..." Befehl die folgenden Codezeilen :

set newLine to "\n"
set varText to paragraphs of varText
set oldTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to newLine
set varText to varText as string
set AppleScript's text item delimiters to oldTID

Was jetzt zurückgegeben wird, enthält Zeichen für neue Zeilen (x0A) , wie sie beginnen müssten, wenn dieser Fehler nicht vorhanden wäre, und nicht Zeichen für Wagenrücklauf (x0D) .


Hinweis: Nach dem Kompilieren wird die Codezeileset newLine to "\n" wie folgt angezeigt:

set newLine to "
"
Wenn ich nur eine Zeile entferne, schlagen Sie vor, dass ich das Semikolon einfüge? Ich habe es in beide Richtungen versucht (mit und ohne Semikolon) und es scheint so oder so gut zu funktionieren, aber ich frage nur nach Ihrer Präferenz.
@rubik's sphere, das Semikolon wird in diesem Anwendungsfall nur als Trennzeichen benötigt, wenn mehr als ein Bereich angegeben wird. Welche Zeile möchten Sie löschen?
Hast du den letzten Teil meiner neuen Frage gesehen? Es ist unmöglich, diese Methode zweimal für dieselbe Variable auszuführen, was bedeuten muss, dass Ihre Methode zum Löschen von Zeilen die Zeichen für die neue Zeile (x0A) in etwas anderes ändert (beim Löschen einer Zeile).

Lassen Sie uns dieses Skript in kleinere Teile zerlegen und dann alles in einem AppleScript zusammenfassen.

Dieser Ansatz ist vollständig in AppleScript geschrieben und erfordert keine externen Tools. Die Verwendung externer Tools wie perloder sedführt wahrscheinlich zu viel kürzeren Lösungen, aber Sie haben in anderen Fragen erwähnt, dass Sie AppleScript lernen möchten.

1. Mit Trennzeichen trennen

Sie können das Trennzeichenverhalten von AppleScript verwenden, um eine Zeichenfolge zu teilen . Sie können das Trennzeichen wie gewünscht ändern in return, linefeed, oder sogar Zeichen wie =:

 -- http://macscripter.net/viewtopic.php?id=24473
 to split(someText, delimiter)
     set AppleScript's text item delimiters to delimiter
     set someText to someText's text items
     set AppleScript's text item delimiters to {""} --> restore delimiters to default value
     return someText
 end split

 set myText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")
 set myLines to split(myText, return)

2. Liste filtern

Mit der zurückgegebenen Liste können Sie die unerwünschten Elemente mithilfe einer Schleife herausfiltern :

 -- http://macscripter.net/viewtopic.php?id=24525
 set indexesToDelete to {1, 4}
 set cleanList to {}

 repeat with i from 1 to count myLines
     if i is not in indexesToDelete then set cleanList's end to myLines's item i
 end repeat

3. Kombinieren Sie die Artikel

Die gefilterte Satzliste kann mit einer weiteren Schleife neu kombiniert werden:

-- Combine the filtered list into a string
set myResult to ""
repeat with i from 1 to count cleanList
    if myResult is "" then
        set myResult to cleanList's item i
    else
        set myResult to myResult & return & cleanList's item i
    end if
end repeat

Komplett AppleScript

Die Kombination dieser Snippets führt zu folgendem Code:

-- Get the text to work with
set myText to (return & "This is sentence 1." & return & "This is sentence 2." & return & "This is sentence 3." & return & "This is sentence 4.")

-- Split the text into lines based on 'return' delimiter
set myLines to split(myText, return)

-- Filter out indexes 1 and 4 using a loop
set indexesToDelete to {1, 4}
set cleanList to {}
repeat with i from 1 to count myLines
    if i is not in indexesToDelete then set cleanList's end to myLines's item i
end repeat

-- Combine the filtered list into a string
set myResult to ""
repeat with i from 1 to count cleanList
    if myResult is "" then
        set myResult to cleanList's item i
    else
        set myResult to myResult & return & cleanList's item i
    end if
end repeat

-- Final string
myResult

to split(someText, delimiter)
    set AppleScript's text item delimiters to delimiter
    set someText to someText's text items
    set AppleScript's text item delimiters to {""} --> restore delimiters to default value
    return someText
end split

Das obige Skript könnte durch Kombinieren der Filter- und Rekombinationsschleifen reduziert werden. Ich habe diese als separate Aufgaben belassen, um ihre Rollen besser zu demonstrieren.

Ihre Strategie leidet auch unter genau demselben Fehler, der in der ursprünglichen Methode von @user3439894 gefunden wurde (der Fehler wird im Abschnitt „Bearbeiten:“ meines Beitrags beschrieben). Das heißt, wenn myTextZeilenvorschübe anstelle von Zeilenumbrüchen enthalten sind und Sie die Zeile verwenden: set myLines to split(myText, linefeed), konvertiert Ihr Code jeden Zeilenvorschub, der im Text vorhanden ist, in einen Zeilenumbruch, wodurch es unmöglich wird, dass dieselbe Textvariable Ihre Methode mehr als einmal erfolgreich durchläuft. Ich hatte auf eine Lösung gehofft, die diese problematische Nebenwirkung nicht besitzt; Ich möchte Zeilen aus derselben Variablen mehr als einmal löschen.
@rubiks Sphäre, Graham Milns Antwort leidet nicht unter dem gleichen Fehler, da er keinen Befehl verwendet do shell script , in dem sich der Fehler befindet. Er verwendet returngenau das, was Sie ursprünglich in der Originalversion dieser Frage gezeigt haben! Sie sollten nicht verwenden return, um mehrzeilige Zeichenfolgen zu verketten , sondern stattdessen verwenden linefeed. In der Tat, wenn Sie all be the last returnto linefeedin seiner Antwort ersetzen, würde es wie erwartet funktionieren, indem die x0AZeilenenden beibehalten werden, x0Dwas returnbei Verwendung als textklassenspezifische Zeichenfolgenkonstante der Fall ist.
@ user3439894 Sie haben Recht damit, dass es sich technisch gesehen nicht um den "gleichen" Fehler handelt. Um es klar zu sagen, Grahams Methode hat einen anderen Fehler, aber einen mit genau der gleichen Wirkung wie der Fehler in Ihrer do shell scriptMethode. Dies ist der Test: Wenn Sie in Grahams Antwort Zeilenvorschübe anstelle von Zeilenumbrüchen verwenden, können Sie eine bestimmte Textvariable mehr als einmal durch seine Methode im selben Skript ausführen, wobei alles noch ordnungsgemäß funktioniert (z. B. indem Sie zuerst die zweite Zeile des Absatzes löschen und dann das Löschen der dritten Zeile in zwei separaten Anweisungen)?