#include <cctype>
#include <iostream>
#include <vector>
#include <set>
using namespace std;

struct CustomCompare {
    // 重载operator()
    bool operator()(const pair<char, int>& a, const pair<char, int>& b)const {
        // 先全部转小写
        char lhs = a.first;
        char rhs = b.first;
        if (a.first >= 'A' && a.first <= 'Z') {
            lhs = a.first + 32;
        }
        if (b.first >= 'A' && b.first <= 'Z') {
            rhs = b.first + 32;
        }
        if (lhs != rhs) {
            return lhs < rhs;
        } else {
            // 比较出现的顺序
            return a.second < b.second;
        }
    }
};
int main() {
    // HJ26字符串排序
    string str; // 从键盘输入一个字符串
    std::getline(cin, str);
    // 对字母进行排序,不区分大小写
    /**
     * 按照字母表中的顺序排序(不区分大小写)
     * 同一字母的大小写同时存在时,按照输入顺序排序
     * 非字母字符保持原来的位置不参与排序
     */
    /**
     * 解题思路:
     * 需要记录字符和其出现的位置,可用一个vector<pair{char,index}>进行存放字符和出现的位置
     */
    // 需要记录字符和其出现的位置,可用一个vector<pair{char,index}>进行存放字符和出现的位置
    vector<pair<char, int>> index;
    for (int i = 0; i < str.length(); ++i) {
        index.push_back({str[i], i});
    }
    // 将是字母字符的按照上面的规则进行排序
    // 将字母全部抽取出来
    multiset<pair<char, int>, CustomCompare>
    ch_index; // 需要对multiset中的进行模板特化
    for (auto &[ch, index1] : index) {
        if (isalpha(ch)) {
            // 是字母,插入到新的数组当中
            ch_index.insert({ch, index1});
        }
    }
    // 排完序之后,加上原本非字母字符进行输出
    string res = str; // 先复制一份
    auto it = ch_index.begin();
    for (int i = 0; i < res.length(); ++i) {
        if (isalpha(res[i])) {
            // 换成排好序的
            res[i] = it->first;
            ++it;
        }
    }
    cout << res << endl;
}