Sed Script do wielkich liter „I” w pliku tekstowym

2

Próbuję utworzyć polecenie sed, które kapitalizuje zaimek I w pliku tekstowym. Na przykład „lubię psy”. powinno być „Lubię psy”. Do tej pory mam:

sed 's/ i / I /g'

To nie działa w wielu różnych scenariuszach. Jak gdyby nie ma znaków interpunkcyjnych po I .

Oto lista scenariuszy, o których pomyślałem, że polecenie powinno być w stanie obsłużyć:

  • W jednym wierszu tekstu znajduje się wiele „ i ”. Myślę, że można temu zaradzić, mając gflagę na końcu.
  • I ” ma wokół siebie znaki interpunkcyjne. Na przykład przecinek lub kropka po nim, cytat lub nawias przed nim lub po nim.
  • I ” to pierwszy lub ostatni znak w linii. Oznacza to, że nie można po prostu sprawdzić odstępów lub interpunkcji.
  • Każde zwykłe „ ja ” w słowie jest pozostawione w spokoju. Na przykład „f I Opłaty i ghter” nie powinien być przekształcony „f I Opłaty ja ghter”.
nickeb96
źródło

Odpowiedzi:

5

Zakładając, że używasz GNU sed, jednym ze sposobów jest

sed 's/\([[:space:]]\|[[:punct:]]\)i\([[:space:]]\|[[:punct:]]\)/\1I\2/g'

czy coś takiego. Pozostaje to w przypadku linii zaczynającej się od „i like dogs”, ponieważ przed zaimkiem nie ma spacji. Jednym ze sposobów rozwiązania tego jest

sed 's/\(^\|[[:space:]]\|[[:punct:]]\)i\([[:space:]]\|[[:punct:]]\)/\1I\2/g'

Pozostaje to w przypadku, gdy masz kolejne „i” jak w „ii”, ale nie mogę wymyślić żadnego powodu, dla którego miałoby to nastąpić w tekście angielskim, z wyjątkiem sytuacji, gdy ktoś błędnie napisał „ii sir”, gdy poprawne wyrażenie to „aye” tak, proszę pana.

Istnieją również szorstkie krawędzie, jeśli używasz również małych cyfr rzymskich. Skrypt sed nie będzie w stanie stwierdzić, czy „i” jest zaimkiem czy cyfrą rzymską, ale tak naprawdę nie ma na to dobrego rozwiązania.

użytkownik 10354138
źródło
Obejściem tego i iprzypadku jest dwukrotne zastosowanie transformacji. Można to osiągnąć przez jednego polecenia: sed -e 's…' -e 's…'.
Kamil Maciorowski
Starałem się unikać robienia rzeczy dwa razy, ale przypuszczam, że jeśli push przychodzi do ataku, jest to jedyny sposób.
user10354138,
2

Proste rozwiązanie (z GNU sed):

sed 's/\bi\b/I/g'

Jest to w zasadzie ta sama koncepcja, co druga odpowiedź - zamień „i” na „ja”, jeśli nie jest to część większego słowa.  \bwydaje się nie być wspomniany na stronie podręcznika sed, ale wyjaśniono to w Podręczniku GNU sed :

\b

    Dopasowuje granicę słów; oznacza to, że pasuje, jeśli znak po lewej stronie jest znakiem „słownym”, a znak po prawej stronie jest znakiem „niebędącym słowem” lub odwrotnie.

$ echo "abc %-= def." | sed 's/\b/X/g'
XabcX %-= XdefX.

Nawet instrukcja nie mówi wprost (ale przykład pokazuje), że \bpasuje do początku i końca linii. Nie pasuje do żadnych znaków; dopasowuje ciąg pusty, który pojawia się między znakiem „słowa” a znakiem „nie słowa” (w dowolnej kolejności) lub na początku i na końcu linii (jak ^$). Więc nie musimy się martwić o przechwycenie (za pomocą \(... \)) postaci, które pasują, i zastąpienie ich przez \1i \2. Ponieważ \bnie pasuje do żadnych znaków, to polecenie działa na i i(zmieniając je na I I).

G-Man
źródło